--- /dev/null
--- /dev/null
++root = true
++
++[*.xml]
++indent_style = space
++indent_size = 2
++tab_width = 8
--- /dev/null
--- /dev/null
++.templates_sha: &template_sha 290b79e0e78eab67a83766f4e9691be554fc4afd
++
++include:
++ - project: 'freedesktop/ci-templates'
++ ref: *template_sha
++ file: '/templates/debian.yml'
++ - project: 'freedesktop/ci-templates'
++ ref: *template_sha
++ file: '/templates/ci-fairy.yml'
++
++stages:
++ - review
++ - containers-build
++ - test
++
++variables:
++ FDO_UPSTREAM_REPO: wayland/wayland-protocols
++
++.debian:
++ variables:
++ FDO_DISTRIBUTION_VERSION: bullseye
++ FDO_DISTRIBUTION_PACKAGES: 'build-essential pkg-config meson git ca-certificates libffi-dev libexpat1-dev libxml2-dev'
++ FDO_DISTRIBUTION_TAG: '2022-01-19.0'
++ FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} ./.gitlab-ci/debian-install.sh'
++
++check-commit:
++ extends:
++ - .fdo.ci-fairy
++ stage: review
++ script:
++ - ci-fairy check-commits --signed-off-by --junit-xml=results.xml
++ variables:
++ GIT_DEPTH: 100
++ artifacts:
++ reports:
++ junit: results.xml
++
++container_build:
++ extends:
++ - .debian
++ - .fdo.container-build@debian
++ stage: containers-build
++ variables:
++ GIT_STRATEGY: none
++
++test-meson:
++ stage: test
++ extends:
++ - .debian
++ - .fdo.distribution-image@debian
++ script:
++ - meson build
++ - ninja -C build
++ - meson test -C build
++ - ninja -C build install
++ artifacts:
++ name: wayland-protocols-$CI_COMMIT_SHA
++ when: always
++ paths:
++ - $CI_PROJECT_DIR/build/meson-logs
--- /dev/null
--- /dev/null
++#!/bin/sh -eux
++
++# Note: don't forget to bump FDO_DISTRIBUTION_TAG when editing this file!
++
++git clone --branch 1.20.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland
++cd wayland/
++git show -s HEAD
++meson build/ -Dtests=false -Ddocumentation=false
++ninja -j${FDO_CI_CONCURRENT:-4} -C build/ install
++cd ..
++rm -rf wayland/
++
++echo "/usr/local/lib" >/etc/ld.so.conf.d/local.conf
++ldconfig
--- /dev/null
--- /dev/null
++Copyright © 2008-2013 Kristian Høgsberg
++Copyright © 2010-2013 Intel Corporation
++Copyright © 2013 Rafael Antognolli
++Copyright © 2013 Jasper St. Pierre
++Copyright © 2014 Jonas Ådahl
++Copyright © 2014 Jason Ekstrand
++Copyright © 2014-2015 Collabora, Ltd.
++Copyright © 2015 Red Hat Inc.
++
++Permission is hereby granted, free of charge, to any person obtaining a
++copy of this software and associated documentation files (the "Software"),
++to deal in the Software without restriction, including without limitation
++the rights to use, copy, modify, merge, publish, distribute, sublicense,
++and/or sell copies of the Software, and to permit persons to whom the
++Software is furnished to do so, subject to the following conditions:
++
++The above copyright notice and this permission notice (including the next
++paragraph) shall be included in all copies or substantial portions of the
++Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++DEALINGS IN THE SOFTWARE.
++
++---
++
++The above is the version of the MIT "Expat" License used by X.org:
++
++ http://cgit.freedesktop.org/xorg/xserver/tree/COPYING
--- /dev/null
--- /dev/null
++# wayland-protocols governance
++
++This document governs the maintenance of wayland-protocols and serves to outline
++the broader process for standardization of protocol extensions in the Wayland
++ecosystem.
++
++## 1. Membership
++
++Membership in wayland-protocols is offered to stakeholders in the Wayland
++ecosystem who have an interest in participating in protocol extension
++standardization.
++
++### 1.1. Membership requirements
++
++1. Membership is extended to projects, rather than individuals.
++2. Members represent general-purpose projects with a stake in multiple Wayland
++ protocols (e.g. compositors, GUI toolkits, etc), rather than special-purpose
++ applications with a stake in only one or two.
++3. Each project must provide one or two named individuals as points-of-contact
++ for that project who can be reached to discuss protocol-related matters.
++4. During a vote, if two points-of-contact for the same member disagree, the
++ member's vote is considered blank.
++
++### 1.2. Becoming a member
++
++1. New members who meet the criteria outlined in 1.1 are established by
++ invitation from an existing member. Projects hoping to join should reach out
++ to an existing member asking for this invitation.
++2. New members shall write to the wayland-devel mailing list stating their
++ intention of joining and their sponsor.
++3. The sponsor shall respond acknowledging their sponsorship of the membership.
++4. A 14 day discussion period for comments from wayland-protocols members will
++ be held.
++5. At the conclusion of the discussion period, the new membership is established
++ unless their application was NACKed by a 1/2 majority of all existing members.
++
++### 1.3. Ceasing membership
++
++1. A member may step down by writing their intention to do so to the
++ wayland-devel mailing list.
++2. A removal vote may be called for by an existing member by posting to the
++ wayland-devel mailing list. This begins a 14 day voting & discussion
++ period.
++3. At the conclusion of the voting period, the member is removed if the votes
++ total 2/3rds of all current members.
++4. Removed members are not eligible to apply for membership again for a period
++ of 1 year.
++5. Following a failed vote, the member who called for the vote cannot
++ call for a re-vote or propose any other removal for 90 days.
++
++## 2. Protocols
++
++### 2.1. Protocol namespaces
++
++1. Namespaces are implemented in practice by prefixing each interface name in a
++ protocol definition (XML) with the namespace name, and an underscore (e.g.
++ "xdg_wm_base").
++2. Protocols in a namespace may optionally use the namespace followed by a dash
++ in the name (e.g. "xdg-shell").
++3. The "xdg" namespace is established for protocols letting clients
++ configure its surfaces as "windows", allowing clients to affect how they
++ are managed.
++4. The "wp" namespace is established for protocols generally useful to Wayland
++ implementations (i.e. "plumbing" protocols).
++5. The "ext" namespace is established as a general catch-all for protocols that
++ fit into no other namespace.
++
++### 2.2. Protocol inclusion requirements
++
++1. All protocols found in the "xdg" and "wp" namespaces at the time of writing
++ are grandfathered into their respective namespace without further discussion.
++2. Protocols in the "xdg" and "wp" namespace are eligible for inclusion only if
++ ACKed by at least 3 members.
++3. Protocols in the "xdg" and "wp" namespace are ineligible for inclusion if
++ if NACKed by any member.
++4. Protocols in the "xdg" and "wp" namespaces must have at least 3 open-source
++ implementations (either 1 client + 2 servers, or 2 clients + 1 server) to be
++ eligible for inclusion.
++5. Protocols in the "ext" namespace are eligible for inclusion only if ACKed by
++ at least one other member.
++6. Protocols in the "ext" namespace must have at least one open-source client &
++ one open-source server implementation to be eligible for inclusion.
++7. "Open-source" is defined as distributed with an Open Source Initiative
++ approved license.
++
++### 2.3. Introducing new protocols
++
++1. A new protocol may be proposed by submitting a merge request to the
++ wayland-protocols Gitlab repository.
++2. Protocol proposal posts must include justification for their inclusion in
++ their namespace per the requirements outlined in section 2.2.
++3. An indefinite discussion period for comments from wayland-protocols members
++ will be held, with a minimum duration of 30 days. Protocols which require a
++ certain level of implementation status, ACKs from members, and so on, should
++ use this time to acquire them.
++4. When the proposed protocol meets all requirements for inclusion per section
++ 2.2, and the minimum discussion period has elapsed, the sponsoring member may
++ merge their changes in the wayland-protocol repository.
++5. Amendments to existing protocols may be proposed by the same process, with
++ no minimum discussion period.
++6. Declaring a protocol stable may be proposed by the same process, with the
++ regular 30 day minimum discussion period.
++
++## 3. Protocol adoption documentation
++
++### 3.1. Adoption website
++
++1. This section is informational.
++2. A website will be made available for interested parties to browse the
++ implementation status of protocols included in wayland-protocols.
++3. A statement from each member of wayland-protocols will be included on the
++ site.
++4. Each protocol will be listed along with its approval status from each member.
++5. The approval statuses are:
++ 1. NACK, or "negative acknowledgement", meaning that the member is opposed to
++ the protocol in principle.
++ 2. NOPP, or "no opposition", meaning that the member is not opposed to the
++ protocol in principle, but does not provide an implementation.
++ 3. ACK, or "acknowledged", meaning that the member supports the protocol in
++ principle, but does not provide an implementation.
++ 4. IMPL, or "implemented", meaning that the member supports the protocol and
++ provides an implementation.
++6. Each member may write a short statement expanding on the rationale for their
++ approval status, which will be included on the site.
++7. A supplementary list of implementations will also be provided on the site,
++ which may include implementations supported by non-members.
++
++### 3.2. Changes to the adoption website
++
++1. This section is informational.
++2. A new protocol is added to the website by the sponsoring member at the
++ conclusion of the discussion period (section 2.3.3).
++3. During the discussion period (section 2.3.3), interested parties may express
++ their approval status on the Gitlab merge request. The default approval
++ status for members who do not participate in the discussion is "NOPP".
++4. Members may change their acknowledgement status or support statement at any
++ time after the discussion period (section 2.3.3) has closed by simply merging
++ their update in the wayland-protocols repository.
++
++## 4. Amending this document
++
++1. An amendment to this document may be proposed any member by
++ submitting a merge request on Gitlab.
++2. A 30 day discussion period for comments from wayland-protocols members will
++ be held.
++3. At the conclusion of the discussion period, an amendment will become
++ effective if it's ACKed by at least 2/3rds of all wayland-protocols members,
++ and NACKed by none. The sponsoring member may merge their change to the
++ wayland-protocols repository at this point.
--- /dev/null
--- /dev/null
++# wayland-protocols members
++
++- EFL/Enlightenment: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> (@zmike)
++- GTK/Mutter: Jonas Ådahl <jadahl@gmail.com> (@jadahl),
++ Carlos Garnacho <carlosg@gnome.org> (@carlosg)
++- KWin: Vlad Zahorodnii <vlad.zahorodnii@kde.org> (@zzag),
++ David Edmundson <david@davidedmundson.co.uk> (@davidedmundson)
++- Mir: Christopher James Halse Rogers <raof@ubuntu.com> (@RAOF),
++ Alan Griffiths <alan.griffiths@canonical.com>
++- Qt: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
++ (@eskilblomfeldt)
++- Weston: Pekka Paalanen <pekka.paalanen@collabora.com> (@pq),
++ Daniel Stone <daniel@fooishbar.org> (@daniels)
++- wlroots/Sway: Simon Ser <contact@emersion.fr> (@emersion),
++ Simon Zeni <simon@bl4ckb0ne.ca> (@bl4ckb0ne)
--- /dev/null
--- /dev/null
++# Wayland protocols
++
++wayland-protocols contains Wayland protocols that add functionality not
++available in the Wayland core protocol. Such protocols either add
++completely new functionality, or extend the functionality of some other
++protocol either in Wayland core, or some other protocol in
++wayland-protocols.
++
++A protocol in wayland-protocols consists of a directory containing a set
++of XML files containing the protocol specification, and a README file
++containing detailed state and a list of maintainers.
++
++## Protocol phases
++
++Protocols in general has three phases: the development phase, the testing
++phase, and the stable phase.
++
++In the development phase, a protocol is not officially part of
++wayland-protocols, but is actively being developed, for example by
++iterating over it in a
++[merge
++request](https://gitlab.freedesktop.org/wayland/wayland-protocols/merge_requests),
++or planning it in an
++[issue](https://gitlab.freedesktop.org/wayland/wayland-protocols/issues).
++
++During this phase, patches for clients and compositors are written as a test
++vehicle. Such patches must not be merged in clients and compositors, because
++the protocol can still change.
++
++When a protocol has reached a stage where it is ready for wider adoption,
++and after the [GOVERNANCE section
++2.3](GOVERNANCE.md#2.3-introducing-new-protocols) requirements have been
++met, it enters the "testing" phase. At this point, the protocol is added
++to `staging/` directory of wayland-protocols and made part of a release.
++What this means is that implementation is encouraged in clients and
++compositors where the functionality it specifies is wanted.
++
++Extensions in staging cannot have backward incompatible changes, in that
++sense they are equal to stable extensions. However, they may be completely
++replaced with a new major version, or a different protocol extension all
++together, if design flaws are found in the testing phase.
++
++After a staging protocol has been sufficiently tested in the wild and
++proven adequate, its maintainers and the community at large may declare it
++"stable", meaning it is unexpected to become superseded by a new major
++version.
++
++## Deprecation
++
++A protocol may be deprecated, if it has been replaced by some other
++protocol, or declared undesirable for some other reason. No more changes
++will be made to a deprecated protocol.
++
++## Legacy protocol phases
++
++An "unstable" protocol refers to a protocol categorization policy
++previously used by wayland-protocols, where protocols initially
++placed in the `unstable/` directory had certain naming conventions were
++applied, requiring a backward incompatible change to be declared "stable".
++
++During this phase, protocol extension interface names were in addition to
++the major version postfix also prefixed with `z` to distinguish from
++stable protocols.
++
++## Protocol directory tree structure
++
++Depending on which stage a protocol is in, the protocol is placed within
++the toplevel directory containing the protocols with the same stage.
++Stable protocols are placed in the `stable/` directory, staging protocols
++are placed in the `staging/` directory, and deprecated protocols are
++placed in the `deprecated/` directory.
++
++Unstable protocols (see [Legacy protocol phases](#legacy-protocol-phases))
++can be found in the `unstable/` directory, but new ones should never be
++placed here.
++
++## Protocol development procedure
++
++To propose a new protocol, create a GitLab merge request adding the
++relevant files and Makefile.am entry to the repository with the
++explanation and motivation in the commit message. Protocols are
++organized in namespaces describing their scope ("wp", "xdg" and "ext").
++There are different requirements for each namespace, see [GOVERNANCE
++section 2](GOVERNANCE.md#2-protocols) for more information.
++
++If the new protocol is just an idea, open an issue on the GitLab issue
++tracker. If the protocol isn't ready for complete review yet and is an
++RFC, create a merge request and add the "WIP:" prefix in the title.
++
++To propose changes to existing protocols, create a GitLab merge request.
++
++Please include a `Signed-off-by` line at the end of the commit to certify
++that you wrote it or otherwise have the right to pass it on as an
++open-source patch. See the
++[Developer Certificate of Origin](https://developercertificate.org/) for
++a formal definition.
++
++## Interface naming convention
++
++All protocols should avoid using generic namespaces or no namespaces in
++the protocol interface names in order to minimize risk that the generated
++C API collides with other C API. Interface names that may collide with
++interface names from other protocols should also be avoided.
++
++For generic protocols not limited to certain configurations (such as
++specific desktop environment or operating system) the `wp_` prefix
++should be used on all interfaces in the protocol.
++
++For protocols allowing clients to configure how their windows are
++managed, the `xdg_` prefix should be used.
++
++For operating system specific protocols, the interfaces should be
++prefixed with both `wp_` and the operating system, for example
++`wp_linux_`, or `wp_freebsd_`, etc.
++
++For more information about namespaces, see [GOVERNANCE section 2.1
++](GOVERNANCE.md#21-protocol-namespaces).
++
++Each new protocol XML file must include a major version postfix, starting
++with `-v1`. The purpose of this postfix is to make it possible to
++distinguish between backward incompatible major versions of the same
++protocol.
++
++The interfaces in the protocol XML file should as well have the same
++major version postfix in their names.
++
++For example, the protocol `foo-bar` may have a XML file
++`foo-bar/foo-bar-v1.xml`, consisting of the interface `wp_foo_bar_v1`,
++corresponding to the major version 1, as well as the newer version
++`foo-bar/foo-bar-v2.xml` consisting of the interface `wp_foo_bar_v2`,
++corresponding to the major version 2.
++
++## Include a disclaimer
++
++Include the following disclaimer:
++
++```
++Warning! The protocol described in this file is currently in the testing
++phase. Backward compatible changes may be added together with the
++corresponding interface version bump. Backward incompatible changes can
++only be done by creating a new major version of the extension.
++```
++
++## Use of RFC 2119 keywords
++
++Descriptions of all new protocols must use (in lowercase) and adhere to the
++proper meaning of the keywords described in
++[RFC 2119](https://www.rfc-editor.org/info/rfc2119).
++
++All protocol descriptions that follow the guidelines in RFC 2119 must
++incorporate the following text in their toplevel protocol description section:
++
++```
++The key words "must", "must not", "required", "shall", "shall not", "should",
++"should not", "recommended", "may", and "optional" in this document are to
++be interpreted as described in IETF RFC 2119.
++```
++
++Note that not all existing protocol descriptions conform to RFC 2119. Protocol
++maintainers are encouraged to audit their descriptions, update them as needed
++to follow RFC 2119 guidelines, and mark them as conformant in the way described
++in the previous paragraph.
++
++## Backward compatible protocol changes
++
++A protocol may receive backward compatible additions and changes. This
++is to be done in the general Wayland way, using `version` and `since` XML
++element attributes.
++
++## Backward incompatible protocol changes
++
++While not preferred, a protocol may at any stage, especially during the
++testing phase, when it is located in the `staging/` directory, see
++backward incompatible changes.
++
++Assuming a backward incompatible change is needed, the procedure for how to
++do so is the following:
++
++- Make a copy of the XML file with the major version increased by 1.
++- Increase the major version number in the protocol XML by 1.
++- Increase the major version number in all of the interfaces in the
++ XML by 1.
++- Reset the interface version number (interface version attribute) of all
++ the interfaces to 1.
++- Remove all of the `since` attributes.
++
++## Declaring a protocol stable
++
++Once it has been concluded that a protocol been proven adequate in
++production, and that it is deemed unlikely to receive any backward
++incompatible changes, it may be declared stable.
++
++The procedure of doing this is the following:
++
++- Create a new directory in the `stable/` toplevel directory with the
++ same name as the protocol directory in the `staging/` directory.
++- Copy the final version of the XML that is the version that was
++ decided to be declared stable into the new directory. The target name
++ should be the same name as the protocol directory but with the `.xml`
++ suffix.
++- Remove the disclaimer about the protocol being in the testing phase.
++- Update the `README` file in the staging directory and create a new
++ `README` file in the new directory.
++- Replace the disclaimer in the protocol files left in the staging/
++ directory with the following:
++
++```
++Disclaimer: This protocol extension has been marked stable. This copy is
++no longer used and only retained for backwards compatibility. The
++canonical version can be found in the stable/ directory.
++```
++
++Note that the major version of the stable protocol extension, as well as
++all the interface versions and names, must remain unchanged.
++
++There are other requirements for declaring a protocol stable, see
++[GOVERNANCE section 2.3](GOVERNANCE.md#23-introducing-new-protocols).
++
++## Releases
++
++Each release of wayland-protocols finalizes the version of the protocols
++to their state they had at that time.
++
++## Gitlab conventions
++
++### Triaging merge requests
++
++New merge requests should be triaged. Doing so requires the one doing the
++triage to add a set of initial labels:
++
++~"New Protocol" - For a new protocol being added. If it's an amendment to
++an existing protocol, apply the label of the corresponding protocol
++instead. If none exist, create it.
++
++~"Needs acks" - If the protocol needs one or more acknowledgements.
++
++~"Needs implementations" - If there are not enough implementations of the
++protocol.
++
++~"Needs review" - If the protocol is in need of review.
++
++~"In 30 day discussion period" - If the protocol needs a 30 day discussion
++period.
++
++For the meaning and requirement of acknowledgments and available
++implementations, see the GOVERNANCE.md document.
++
++### Managing merge requests
++
++When merge requests get their needed feedback and items, remove the
++corresponding label that marks it as needing something. For example, if a
++merge request receives all the required acknowledgments, remove the
++~"Needs acks" label, or if 30 days passed since opening, remove any
++~"In 30 day discussion period" label.
++
++### Nacking a merge request
++
++If the inclusion of a merge request is denied due to one or more Nacks, add
++the ~Nacked label.
--- /dev/null
--- /dev/null
++project('wayland-protocols',
++ version: '1.26',
++ meson_version: '>= 0.55.0',
++ license: 'MIT/Expat',
++)
++
++wayland_protocols_version = meson.project_version()
++
++fs = import('fs')
++
++stable_protocols = [
++ 'presentation-time',
++ 'viewporter',
++ 'xdg-shell',
++]
++
++unstable_protocols = {
++ 'fullscreen-shell': ['v1'],
++ 'idle-inhibit': ['v1'],
++ 'input-method': ['v1'],
++ 'input-timestamps': ['v1'],
++ 'keyboard-shortcuts-inhibit': ['v1'],
++ 'linux-dmabuf': ['v1'],
++ 'linux-explicit-synchronization': ['v1'],
++ 'pointer-constraints': ['v1'],
++ 'pointer-gestures': ['v1'],
++ 'primary-selection': ['v1'],
++ 'relative-pointer': ['v1'],
++ 'tablet': ['v1', 'v2'],
++ 'text-input': ['v1', 'v3'],
++ 'xdg-decoration': ['v1'],
++ 'xdg-foreign': ['v1', 'v2'],
++ 'xdg-output': ['v1'],
++ 'xdg-shell': ['v5', 'v6'],
++ 'xwayland-keyboard-grab': ['v1'],
++}
++
++staging_protocols = {
++ 'xdg-activation': ['v1'],
++ 'drm-lease': ['v1'],
++ 'ext-session-lock': ['v1'],
++ 'single-pixel-buffer': ['v1'],
++}
++
++protocol_files = []
++
++foreach name : stable_protocols
++ protocol_files += ['stable/@0@/@0@.xml'.format(name)]
++endforeach
++
++foreach name : staging_protocols.keys()
++ foreach version : staging_protocols.get(name)
++ protocol_files += [
++ 'staging/@0@/@0@-@1@.xml'.format(name, version)
++ ]
++ endforeach
++endforeach
++
++foreach name : unstable_protocols.keys()
++ foreach version : unstable_protocols.get(name)
++ protocol_files += [
++ 'unstable/@0@/@0@-unstable-@1@.xml'.format(name, version)
++ ]
++ endforeach
++endforeach
++
++# Check that each protocol has a README
++foreach protocol_file : protocol_files
++ dir = fs.parent(protocol_file)
++ if not fs.is_file(dir + '/README')
++ error('Missing README in @0@'.format(protocol_file))
++ endif
++endforeach
++
++foreach protocol_file : protocol_files
++ protocol_install_dir = fs.parent(join_paths(
++ get_option('datadir'),
++ 'wayland-protocols',
++ protocol_file,
++ ))
++ install_data(
++ protocol_file,
++ install_dir: protocol_install_dir,
++ )
++endforeach
++
++wayland_protocols_srcdir = meson.current_source_dir()
++
++pkgconfig_configuration = configuration_data()
++pkgconfig_configuration.set('prefix', get_option('prefix'))
++pkgconfig_configuration.set('datarootdir', '${prefix}/@0@'.format(get_option('datadir')))
++pkgconfig_configuration.set('abs_top_srcdir', wayland_protocols_srcdir)
++pkgconfig_configuration.set('PACKAGE', 'wayland-protocols')
++pkgconfig_configuration.set('WAYLAND_PROTOCOLS_VERSION', wayland_protocols_version)
++
++pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig')
++configure_file(
++ input: 'wayland-protocols.pc.in',
++ output: 'wayland-protocols.pc',
++ configuration: pkgconfig_configuration,
++ install_dir: pkg_install_dir,
++)
++
++configure_file(
++ input: 'wayland-protocols-uninstalled.pc.in',
++ output: 'wayland-protocols-uninstalled.pc',
++ configuration: pkgconfig_configuration,
++)
++
++wayland_protocols = declare_dependency(
++ variables: {
++ 'pkgdatadir': wayland_protocols_srcdir,
++ },
++)
++
++meson.override_dependency('wayland-protocols', wayland_protocols)
++
++if get_option('tests')
++ subdir('tests')
++endif
--- /dev/null
--- /dev/null
++option('tests',
++ type: 'boolean',
++ value: true,
++ description: 'Build the tests')
--- /dev/null
--- /dev/null
++Presentation time protocol
++
++Maintainers:
++Pekka Paalanen <pekka.paalanen@collabora.co.uk>
++
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="presentation_time">
++<!-- wrap:70 -->
++
++ <copyright>
++ Copyright © 2013-2014 Collabora, Ltd.
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="wp_presentation" version="1">
++ <description summary="timed presentation related wl_surface requests">
++
++<!-- Introduction -->
++
++ The main feature of this interface is accurate presentation
++ timing feedback to ensure smooth video playback while maintaining
++ audio/video synchronization. Some features use the concept of a
++ presentation clock, which is defined in the
++ presentation.clock_id event.
++
++ A content update for a wl_surface is submitted by a
++ wl_surface.commit request. Request 'feedback' associates with
++ the wl_surface.commit and provides feedback on the content
++ update, particularly the final realized presentation time.
++
++<!-- Completing presentation -->
++
++ When the final realized presentation time is available, e.g.
++ after a framebuffer flip completes, the requested
++ presentation_feedback.presented events are sent. The final
++ presentation time can differ from the compositor's predicted
++ display update time and the update's target time, especially
++ when the compositor misses its target vertical blanking period.
++ </description>
++
++ <enum name="error">
++ <description summary="fatal presentation errors">
++ These fatal protocol errors may be emitted in response to
++ illegal presentation requests.
++ </description>
++ <entry name="invalid_timestamp" value="0"
++ summary="invalid value in tv_nsec"/>
++ <entry name="invalid_flag" value="1"
++ summary="invalid flag"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="unbind from the presentation interface">
++ Informs the server that the client will no longer be using
++ this protocol object. Existing objects created by this object
++ are not affected.
++ </description>
++ </request>
++
++ <request name="feedback">
++ <description summary="request presentation feedback information">
++ Request presentation feedback for the current content submission
++ on the given surface. This creates a new presentation_feedback
++ object, which will deliver the feedback information once. If
++ multiple presentation_feedback objects are created for the same
++ submission, they will all deliver the same information.
++
++ For details on what information is returned, see the
++ presentation_feedback interface.
++ </description>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="target surface"/>
++ <arg name="callback" type="new_id" interface="wp_presentation_feedback"
++ summary="new feedback object"/>
++ </request>
++
++ <event name="clock_id">
++ <description summary="clock ID for timestamps">
++ This event tells the client in which clock domain the
++ compositor interprets the timestamps used by the presentation
++ extension. This clock is called the presentation clock.
++
++ The compositor sends this event when the client binds to the
++ presentation interface. The presentation clock does not change
++ during the lifetime of the client connection.
++
++ The clock identifier is platform dependent. On Linux/glibc,
++ the identifier value is one of the clockid_t values accepted
++ by clock_gettime(). clock_gettime() is defined by
++ POSIX.1-2001.
++
++ Timestamps in this clock domain are expressed as tv_sec_hi,
++ tv_sec_lo, tv_nsec triples, each component being an unsigned
++ 32-bit value. Whole seconds are in tv_sec which is a 64-bit
++ value combined from tv_sec_hi and tv_sec_lo, and the
++ additional fractional part in tv_nsec as nanoseconds. Hence,
++ for valid timestamps tv_nsec must be in [0, 999999999].
++
++ Note that clock_id applies only to the presentation clock,
++ and implies nothing about e.g. the timestamps used in the
++ Wayland core protocol input events.
++
++ Compositors should prefer a clock which does not jump and is
++ not slewed e.g. by NTP. The absolute value of the clock is
++ irrelevant. Precision of one millisecond or better is
++ recommended. Clients must be able to query the current clock
++ value directly, not by asking the compositor.
++ </description>
++ <arg name="clk_id" type="uint" summary="platform clock identifier"/>
++ </event>
++
++ </interface>
++
++ <interface name="wp_presentation_feedback" version="1">
++ <description summary="presentation time feedback event">
++ A presentation_feedback object returns an indication that a
++ wl_surface content update has become visible to the user.
++ One object corresponds to one content update submission
++ (wl_surface.commit). There are two possible outcomes: the
++ content update is presented to the user, and a presentation
++ timestamp delivered; or, the user did not see the content
++ update because it was superseded or its surface destroyed,
++ and the content update is discarded.
++
++ Once a presentation_feedback object has delivered a 'presented'
++ or 'discarded' event it is automatically destroyed.
++ </description>
++
++ <event name="sync_output">
++ <description summary="presentation synchronized to this output">
++ As presentation can be synchronized to only one output at a
++ time, this event tells which output it was. This event is only
++ sent prior to the presented event.
++
++ As clients may bind to the same global wl_output multiple
++ times, this event is sent for each bound instance that matches
++ the synchronized output. If a client has not bound to the
++ right wl_output global at all, this event is not sent.
++ </description>
++ <arg name="output" type="object" interface="wl_output"
++ summary="presentation output"/>
++ </event>
++
++ <enum name="kind" bitfield="true">
++ <description summary="bitmask of flags in presented event">
++ These flags provide information about how the presentation of
++ the related content update was done. The intent is to help
++ clients assess the reliability of the feedback and the visual
++ quality with respect to possible tearing and timings.
++ </description>
++ <entry name="vsync" value="0x1">
++ <description summary="presentation was vsync'd">
++ The presentation was synchronized to the "vertical retrace" by
++ the display hardware such that tearing does not happen.
++ Relying on software scheduling is not acceptable for this
++ flag. If presentation is done by a copy to the active
++ frontbuffer, then it must guarantee that tearing cannot
++ happen.
++ </description>
++ </entry>
++ <entry name="hw_clock" value="0x2">
++ <description summary="hardware provided the presentation timestamp">
++ The display hardware provided measurements that the hardware
++ driver converted into a presentation timestamp. Sampling a
++ clock in software is not acceptable for this flag.
++ </description>
++ </entry>
++ <entry name="hw_completion" value="0x4">
++ <description summary="hardware signalled the start of the presentation">
++ The display hardware signalled that it started using the new
++ image content. The opposite of this is e.g. a timer being used
++ to guess when the display hardware has switched to the new
++ image content.
++ </description>
++ </entry>
++ <entry name="zero_copy" value="0x8">
++ <description summary="presentation was done zero-copy">
++ The presentation of this update was done zero-copy. This means
++ the buffer from the client was given to display hardware as
++ is, without copying it. Compositing with OpenGL counts as
++ copying, even if textured directly from the client buffer.
++ Possible zero-copy cases include direct scanout of a
++ fullscreen surface and a surface on a hardware overlay.
++ </description>
++ </entry>
++ </enum>
++
++ <event name="presented" type="destructor">
++ <description summary="the content update was displayed">
++ The associated content update was displayed to the user at the
++ indicated time (tv_sec_hi/lo, tv_nsec). For the interpretation of
++ the timestamp, see presentation.clock_id event.
++
++ The timestamp corresponds to the time when the content update
++ turned into light the first time on the surface's main output.
++ Compositors may approximate this from the framebuffer flip
++ completion events from the system, and the latency of the
++ physical display path if known.
++
++ This event is preceded by all related sync_output events
++ telling which output's refresh cycle the feedback corresponds
++ to, i.e. the main output for the surface. Compositors are
++ recommended to choose the output containing the largest part
++ of the wl_surface, or keeping the output they previously
++ chose. Having a stable presentation output association helps
++ clients predict future output refreshes (vblank).
++
++ The 'refresh' argument gives the compositor's prediction of how
++ many nanoseconds after tv_sec, tv_nsec the very next output
++ refresh may occur. This is to further aid clients in
++ predicting future refreshes, i.e., estimating the timestamps
++ targeting the next few vblanks. If such prediction cannot
++ usefully be done, the argument is zero.
++
++ If the output does not have a constant refresh rate, explicit
++ video mode switches excluded, then the refresh argument must
++ be zero.
++
++ The 64-bit value combined from seq_hi and seq_lo is the value
++ of the output's vertical retrace counter when the content
++ update was first scanned out to the display. This value must
++ be compatible with the definition of MSC in
++ GLX_OML_sync_control specification. Note, that if the display
++ path has a non-zero latency, the time instant specified by
++ this counter may differ from the timestamp's.
++
++ If the output does not have a concept of vertical retrace or a
++ refresh cycle, or the output device is self-refreshing without
++ a way to query the refresh count, then the arguments seq_hi
++ and seq_lo must be zero.
++ </description>
++ <arg name="tv_sec_hi" type="uint"
++ summary="high 32 bits of the seconds part of the presentation timestamp"/>
++ <arg name="tv_sec_lo" type="uint"
++ summary="low 32 bits of the seconds part of the presentation timestamp"/>
++ <arg name="tv_nsec" type="uint"
++ summary="nanoseconds part of the presentation timestamp"/>
++ <arg name="refresh" type="uint" summary="nanoseconds till next refresh"/>
++ <arg name="seq_hi" type="uint"
++ summary="high 32 bits of refresh counter"/>
++ <arg name="seq_lo" type="uint"
++ summary="low 32 bits of refresh counter"/>
++ <arg name="flags" type="uint" enum="kind" summary="combination of 'kind' values"/>
++ </event>
++
++ <event name="discarded" type="destructor">
++ <description summary="the content update was not displayed">
++ The content update was never displayed to the user.
++ </description>
++ </event>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++Viewporter: cropping and scaling extension for surface contents
++
++Previously known as wl_scaler.
++
++Maintainers:
++Pekka Paalanen <pekka.paalanen@collabora.co.uk>
++
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="viewporter">
++
++ <copyright>
++ Copyright © 2013-2016 Collabora, Ltd.
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="wp_viewporter" version="1">
++ <description summary="surface cropping and scaling">
++ The global interface exposing surface cropping and scaling
++ capabilities is used to instantiate an interface extension for a
++ wl_surface object. This extended interface will then allow
++ cropping and scaling the surface contents, effectively
++ disconnecting the direct relationship between the buffer and the
++ surface size.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="unbind from the cropping and scaling interface">
++ Informs the server that the client will not be using this
++ protocol object anymore. This does not affect any other objects,
++ wp_viewport objects included.
++ </description>
++ </request>
++
++ <enum name="error">
++ <entry name="viewport_exists" value="0"
++ summary="the surface already has a viewport object associated"/>
++ </enum>
++
++ <request name="get_viewport">
++ <description summary="extend surface interface for crop and scale">
++ Instantiate an interface extension for the given wl_surface to
++ crop and scale its content. If the given wl_surface already has
++ a wp_viewport object associated, the viewport_exists
++ protocol error is raised.
++ </description>
++ <arg name="id" type="new_id" interface="wp_viewport"
++ summary="the new viewport interface id"/>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="the surface"/>
++ </request>
++ </interface>
++
++ <interface name="wp_viewport" version="1">
++ <description summary="crop and scale interface to a wl_surface">
++ An additional interface to a wl_surface object, which allows the
++ client to specify the cropping and scaling of the surface
++ contents.
++
++ This interface works with two concepts: the source rectangle (src_x,
++ src_y, src_width, src_height), and the destination size (dst_width,
++ dst_height). The contents of the source rectangle are scaled to the
++ destination size, and content outside the source rectangle is ignored.
++ This state is double-buffered, and is applied on the next
++ wl_surface.commit.
++
++ The two parts of crop and scale state are independent: the source
++ rectangle, and the destination size. Initially both are unset, that
++ is, no scaling is applied. The whole of the current wl_buffer is
++ used as the source, and the surface size is as defined in
++ wl_surface.attach.
++
++ If the destination size is set, it causes the surface size to become
++ dst_width, dst_height. The source (rectangle) is scaled to exactly
++ this size. This overrides whatever the attached wl_buffer size is,
++ unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface
++ has no content and therefore no size. Otherwise, the size is always
++ at least 1x1 in surface local coordinates.
++
++ If the source rectangle is set, it defines what area of the wl_buffer is
++ taken as the source. If the source rectangle is set and the destination
++ size is not set, then src_width and src_height must be integers, and the
++ surface size becomes the source rectangle size. This results in cropping
++ without scaling. If src_width or src_height are not integers and
++ destination size is not set, the bad_size protocol error is raised when
++ the surface state is applied.
++
++ The coordinate transformations from buffer pixel coordinates up to
++ the surface-local coordinates happen in the following order:
++ 1. buffer_transform (wl_surface.set_buffer_transform)
++ 2. buffer_scale (wl_surface.set_buffer_scale)
++ 3. crop and scale (wp_viewport.set*)
++ This means, that the source rectangle coordinates of crop and scale
++ are given in the coordinates after the buffer transform and scale,
++ i.e. in the coordinates that would be the surface-local coordinates
++ if the crop and scale was not applied.
++
++ If src_x or src_y are negative, the bad_value protocol error is raised.
++ Otherwise, if the source rectangle is partially or completely outside of
++ the non-NULL wl_buffer, then the out_of_buffer protocol error is raised
++ when the surface state is applied. A NULL wl_buffer does not raise the
++ out_of_buffer error.
++
++ If the wl_surface associated with the wp_viewport is destroyed,
++ all wp_viewport requests except 'destroy' raise the protocol error
++ no_surface.
++
++ If the wp_viewport object is destroyed, the crop and scale
++ state is removed from the wl_surface. The change will be applied
++ on the next wl_surface.commit.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="remove scaling and cropping from the surface">
++ The associated wl_surface's crop and scale state is removed.
++ The change is applied on the next wl_surface.commit.
++ </description>
++ </request>
++
++ <enum name="error">
++ <entry name="bad_value" value="0"
++ summary="negative or zero values in width or height"/>
++ <entry name="bad_size" value="1"
++ summary="destination size is not integer"/>
++ <entry name="out_of_buffer" value="2"
++ summary="source rectangle extends outside of the content area"/>
++ <entry name="no_surface" value="3"
++ summary="the wl_surface was destroyed"/>
++ </enum>
++
++ <request name="set_source">
++ <description summary="set the source rectangle for cropping">
++ Set the source rectangle of the associated wl_surface. See
++ wp_viewport for the description, and relation to the wl_buffer
++ size.
++
++ If all of x, y, width and height are -1.0, the source rectangle is
++ unset instead. Any other set of values where width or height are zero
++ or negative, or x or y are negative, raise the bad_value protocol
++ error.
++
++ The crop and scale state is double-buffered state, and will be
++ applied on the next wl_surface.commit.
++ </description>
++ <arg name="x" type="fixed" summary="source rectangle x"/>
++ <arg name="y" type="fixed" summary="source rectangle y"/>
++ <arg name="width" type="fixed" summary="source rectangle width"/>
++ <arg name="height" type="fixed" summary="source rectangle height"/>
++ </request>
++
++ <request name="set_destination">
++ <description summary="set the surface size for scaling">
++ Set the destination size of the associated wl_surface. See
++ wp_viewport for the description, and relation to the wl_buffer
++ size.
++
++ If width is -1 and height is -1, the destination size is unset
++ instead. Any other pair of values for width and height that
++ contains zero or negative values raises the bad_value protocol
++ error.
++
++ The crop and scale state is double-buffered state, and will be
++ applied on the next wl_surface.commit.
++ </description>
++ <arg name="width" type="int" summary="surface width"/>
++ <arg name="height" type="int" summary="surface height"/>
++ </request>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++xdg shell protocol
++
++Maintainers:
++Jonas Ådahl <jadahl@gmail.com>
++Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_shell">
++
++ <copyright>
++ Copyright © 2008-2013 Kristian Høgsberg
++ Copyright © 2013 Rafael Antognolli
++ Copyright © 2013 Jasper St. Pierre
++ Copyright © 2010-2013 Intel Corporation
++ Copyright © 2015-2017 Samsung Electronics Co., Ltd
++ Copyright © 2015-2017 Red Hat Inc.
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="xdg_wm_base" version="5">
++ <description summary="create desktop-style surfaces">
++ The xdg_wm_base interface is exposed as a global object enabling clients
++ to turn their wl_surfaces into windows in a desktop environment. It
++ defines the basic functionality needed for clients and the compositor to
++ create windows that can be dragged, resized, maximized, etc, as well as
++ creating transient windows such as popup menus.
++ </description>
++
++ <enum name="error">
++ <entry name="role" value="0" summary="given wl_surface has another role"/>
++ <entry name="defunct_surfaces" value="1"
++ summary="xdg_wm_base was destroyed before children"/>
++ <entry name="not_the_topmost_popup" value="2"
++ summary="the client tried to map or destroy a non-topmost popup"/>
++ <entry name="invalid_popup_parent" value="3"
++ summary="the client specified an invalid popup parent surface"/>
++ <entry name="invalid_surface_state" value="4"
++ summary="the client provided an invalid surface state"/>
++ <entry name="invalid_positioner" value="5"
++ summary="the client provided an invalid positioner"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy xdg_wm_base">
++ Destroy this xdg_wm_base object.
++
++ Destroying a bound xdg_wm_base object while there are surfaces
++ still alive created by this xdg_wm_base object instance is illegal
++ and will result in a protocol error.
++ </description>
++ </request>
++
++ <request name="create_positioner">
++ <description summary="create a positioner object">
++ Create a positioner object. A positioner object is used to position
++ surfaces relative to some parent surface. See the interface description
++ and xdg_surface.get_popup for details.
++ </description>
++ <arg name="id" type="new_id" interface="xdg_positioner"/>
++ </request>
++
++ <request name="get_xdg_surface">
++ <description summary="create a shell surface from a surface">
++ This creates an xdg_surface for the given surface. While xdg_surface
++ itself is not a role, the corresponding surface may only be assigned
++ a role extending xdg_surface, such as xdg_toplevel or xdg_popup. It is
++ illegal to create an xdg_surface for a wl_surface which already has an
++ assigned role and this will result in a protocol error.
++
++ This creates an xdg_surface for the given surface. An xdg_surface is
++ used as basis to define a role to a given surface, such as xdg_toplevel
++ or xdg_popup. It also manages functionality shared between xdg_surface
++ based surface roles.
++
++ See the documentation of xdg_surface for more details about what an
++ xdg_surface is and how it is used.
++ </description>
++ <arg name="id" type="new_id" interface="xdg_surface"/>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ </request>
++
++ <request name="pong">
++ <description summary="respond to a ping event">
++ A client must respond to a ping event with a pong request or
++ the client may be deemed unresponsive. See xdg_wm_base.ping.
++ </description>
++ <arg name="serial" type="uint" summary="serial of the ping event"/>
++ </request>
++
++ <event name="ping">
++ <description summary="check if the client is alive">
++ The ping event asks the client if it's still alive. Pass the
++ serial specified in the event back to the compositor by sending
++ a "pong" request back with the specified serial. See xdg_wm_base.pong.
++
++ Compositors can use this to determine if the client is still
++ alive. It's unspecified what will happen if the client doesn't
++ respond to the ping request, or in what timeframe. Clients should
++ try to respond in a reasonable amount of time.
++
++ A compositor is free to ping in any way it wants, but a client must
++ always respond to any xdg_wm_base object it created.
++ </description>
++ <arg name="serial" type="uint" summary="pass this to the pong request"/>
++ </event>
++ </interface>
++
++ <interface name="xdg_positioner" version="5">
++ <description summary="child surface positioner">
++ The xdg_positioner provides a collection of rules for the placement of a
++ child surface relative to a parent surface. Rules can be defined to ensure
++ the child surface remains within the visible area's borders, and to
++ specify how the child surface changes its position, such as sliding along
++ an axis, or flipping around a rectangle. These positioner-created rules are
++ constrained by the requirement that a child surface must intersect with or
++ be at least partially adjacent to its parent surface.
++
++ See the various requests for details about possible rules.
++
++ At the time of the request, the compositor makes a copy of the rules
++ specified by the xdg_positioner. Thus, after the request is complete the
++ xdg_positioner object can be destroyed or reused; further changes to the
++ object will have no effect on previous usages.
++
++ For an xdg_positioner object to be considered complete, it must have a
++ non-zero size set by set_size, and a non-zero anchor rectangle set by
++ set_anchor_rect. Passing an incomplete xdg_positioner object when
++ positioning a surface raises an error.
++ </description>
++
++ <enum name="error">
++ <entry name="invalid_input" value="0" summary="invalid input provided"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_positioner object">
++ Notify the compositor that the xdg_positioner will no longer be used.
++ </description>
++ </request>
++
++ <request name="set_size">
++ <description summary="set the size of the to-be positioned rectangle">
++ Set the size of the surface that is to be positioned with the positioner
++ object. The size is in surface-local coordinates and corresponds to the
++ window geometry. See xdg_surface.set_window_geometry.
++
++ If a zero or negative size is set the invalid_input error is raised.
++ </description>
++ <arg name="width" type="int" summary="width of positioned rectangle"/>
++ <arg name="height" type="int" summary="height of positioned rectangle"/>
++ </request>
++
++ <request name="set_anchor_rect">
++ <description summary="set the anchor rectangle within the parent surface">
++ Specify the anchor rectangle within the parent surface that the child
++ surface will be placed relative to. The rectangle is relative to the
++ window geometry as defined by xdg_surface.set_window_geometry of the
++ parent surface.
++
++ When the xdg_positioner object is used to position a child surface, the
++ anchor rectangle may not extend outside the window geometry of the
++ positioned child's parent surface.
++
++ If a negative size is set the invalid_input error is raised.
++ </description>
++ <arg name="x" type="int" summary="x position of anchor rectangle"/>
++ <arg name="y" type="int" summary="y position of anchor rectangle"/>
++ <arg name="width" type="int" summary="width of anchor rectangle"/>
++ <arg name="height" type="int" summary="height of anchor rectangle"/>
++ </request>
++
++ <enum name="anchor">
++ <entry name="none" value="0"/>
++ <entry name="top" value="1"/>
++ <entry name="bottom" value="2"/>
++ <entry name="left" value="3"/>
++ <entry name="right" value="4"/>
++ <entry name="top_left" value="5"/>
++ <entry name="bottom_left" value="6"/>
++ <entry name="top_right" value="7"/>
++ <entry name="bottom_right" value="8"/>
++ </enum>
++
++ <request name="set_anchor">
++ <description summary="set anchor rectangle anchor">
++ Defines the anchor point for the anchor rectangle. The specified anchor
++ is used derive an anchor point that the child surface will be
++ positioned relative to. If a corner anchor is set (e.g. 'top_left' or
++ 'bottom_right'), the anchor point will be at the specified corner;
++ otherwise, the derived anchor point will be centered on the specified
++ edge, or in the center of the anchor rectangle if no edge is specified.
++ </description>
++ <arg name="anchor" type="uint" enum="anchor"
++ summary="anchor"/>
++ </request>
++
++ <enum name="gravity">
++ <entry name="none" value="0"/>
++ <entry name="top" value="1"/>
++ <entry name="bottom" value="2"/>
++ <entry name="left" value="3"/>
++ <entry name="right" value="4"/>
++ <entry name="top_left" value="5"/>
++ <entry name="bottom_left" value="6"/>
++ <entry name="top_right" value="7"/>
++ <entry name="bottom_right" value="8"/>
++ </enum>
++
++ <request name="set_gravity">
++ <description summary="set child surface gravity">
++ Defines in what direction a surface should be positioned, relative to
++ the anchor point of the parent surface. If a corner gravity is
++ specified (e.g. 'bottom_right' or 'top_left'), then the child surface
++ will be placed towards the specified gravity; otherwise, the child
++ surface will be centered over the anchor point on any axis that had no
++ gravity specified.
++ </description>
++ <arg name="gravity" type="uint" enum="gravity"
++ summary="gravity direction"/>
++ </request>
++
++ <enum name="constraint_adjustment" bitfield="true">
++ <description summary="constraint adjustments">
++ The constraint adjustment value define ways the compositor will adjust
++ the position of the surface, if the unadjusted position would result
++ in the surface being partly constrained.
++
++ Whether a surface is considered 'constrained' is left to the compositor
++ to determine. For example, the surface may be partly outside the
++ compositor's defined 'work area', thus necessitating the child surface's
++ position be adjusted until it is entirely inside the work area.
++
++ The adjustments can be combined, according to a defined precedence: 1)
++ Flip, 2) Slide, 3) Resize.
++ </description>
++ <entry name="none" value="0">
++ <description summary="don't move the child surface when constrained">
++ Don't alter the surface position even if it is constrained on some
++ axis, for example partially outside the edge of an output.
++ </description>
++ </entry>
++ <entry name="slide_x" value="1">
++ <description summary="move along the x axis until unconstrained">
++ Slide the surface along the x axis until it is no longer constrained.
++
++ First try to slide towards the direction of the gravity on the x axis
++ until either the edge in the opposite direction of the gravity is
++ unconstrained or the edge in the direction of the gravity is
++ constrained.
++
++ Then try to slide towards the opposite direction of the gravity on the
++ x axis until either the edge in the direction of the gravity is
++ unconstrained or the edge in the opposite direction of the gravity is
++ constrained.
++ </description>
++ </entry>
++ <entry name="slide_y" value="2">
++ <description summary="move along the y axis until unconstrained">
++ Slide the surface along the y axis until it is no longer constrained.
++
++ First try to slide towards the direction of the gravity on the y axis
++ until either the edge in the opposite direction of the gravity is
++ unconstrained or the edge in the direction of the gravity is
++ constrained.
++
++ Then try to slide towards the opposite direction of the gravity on the
++ y axis until either the edge in the direction of the gravity is
++ unconstrained or the edge in the opposite direction of the gravity is
++ constrained.
++ </description>
++ </entry>
++ <entry name="flip_x" value="4">
++ <description summary="invert the anchor and gravity on the x axis">
++ Invert the anchor and gravity on the x axis if the surface is
++ constrained on the x axis. For example, if the left edge of the
++ surface is constrained, the gravity is 'left' and the anchor is
++ 'left', change the gravity to 'right' and the anchor to 'right'.
++
++ If the adjusted position also ends up being constrained, the resulting
++ position of the flip_x adjustment will be the one before the
++ adjustment.
++ </description>
++ </entry>
++ <entry name="flip_y" value="8">
++ <description summary="invert the anchor and gravity on the y axis">
++ Invert the anchor and gravity on the y axis if the surface is
++ constrained on the y axis. For example, if the bottom edge of the
++ surface is constrained, the gravity is 'bottom' and the anchor is
++ 'bottom', change the gravity to 'top' and the anchor to 'top'.
++
++ The adjusted position is calculated given the original anchor
++ rectangle and offset, but with the new flipped anchor and gravity
++ values.
++
++ If the adjusted position also ends up being constrained, the resulting
++ position of the flip_y adjustment will be the one before the
++ adjustment.
++ </description>
++ </entry>
++ <entry name="resize_x" value="16">
++ <description summary="horizontally resize the surface">
++ Resize the surface horizontally so that it is completely
++ unconstrained.
++ </description>
++ </entry>
++ <entry name="resize_y" value="32">
++ <description summary="vertically resize the surface">
++ Resize the surface vertically so that it is completely unconstrained.
++ </description>
++ </entry>
++ </enum>
++
++ <request name="set_constraint_adjustment">
++ <description summary="set the adjustment to be done when constrained">
++ Specify how the window should be positioned if the originally intended
++ position caused the surface to be constrained, meaning at least
++ partially outside positioning boundaries set by the compositor. The
++ adjustment is set by constructing a bitmask describing the adjustment to
++ be made when the surface is constrained on that axis.
++
++ If no bit for one axis is set, the compositor will assume that the child
++ surface should not change its position on that axis when constrained.
++
++ If more than one bit for one axis is set, the order of how adjustments
++ are applied is specified in the corresponding adjustment descriptions.
++
++ The default adjustment is none.
++ </description>
++ <arg name="constraint_adjustment" type="uint"
++ summary="bit mask of constraint adjustments"/>
++ </request>
++
++ <request name="set_offset">
++ <description summary="set surface position offset">
++ Specify the surface position offset relative to the position of the
++ anchor on the anchor rectangle and the anchor on the surface. For
++ example if the anchor of the anchor rectangle is at (x, y), the surface
++ has the gravity bottom|right, and the offset is (ox, oy), the calculated
++ surface position will be (x + ox, y + oy). The offset position of the
++ surface is the one used for constraint testing. See
++ set_constraint_adjustment.
++
++ An example use case is placing a popup menu on top of a user interface
++ element, while aligning the user interface element of the parent surface
++ with some user interface element placed somewhere in the popup surface.
++ </description>
++ <arg name="x" type="int" summary="surface position x offset"/>
++ <arg name="y" type="int" summary="surface position y offset"/>
++ </request>
++
++ <!-- Version 3 additions -->
++
++ <request name="set_reactive" since="3">
++ <description summary="continuously reconstrain the surface">
++ When set reactive, the surface is reconstrained if the conditions used
++ for constraining changed, e.g. the parent window moved.
++
++ If the conditions changed and the popup was reconstrained, an
++ xdg_popup.configure event is sent with updated geometry, followed by an
++ xdg_surface.configure event.
++ </description>
++ </request>
++
++ <request name="set_parent_size" since="3">
++ <description summary="">
++ Set the parent window geometry the compositor should use when
++ positioning the popup. The compositor may use this information to
++ determine the future state the popup should be constrained using. If
++ this doesn't match the dimension of the parent the popup is eventually
++ positioned against, the behavior is undefined.
++
++ The arguments are given in the surface-local coordinate space.
++ </description>
++ <arg name="parent_width" type="int"
++ summary="future window geometry width of parent"/>
++ <arg name="parent_height" type="int"
++ summary="future window geometry height of parent"/>
++ </request>
++
++ <request name="set_parent_configure" since="3">
++ <description summary="set parent configure this is a response to">
++ Set the serial of an xdg_surface.configure event this positioner will be
++ used in response to. The compositor may use this information together
++ with set_parent_size to determine what future state the popup should be
++ constrained using.
++ </description>
++ <arg name="serial" type="uint"
++ summary="serial of parent configure event"/>
++ </request>
++ </interface>
++
++ <interface name="xdg_surface" version="5">
++ <description summary="desktop user interface surface base interface">
++ An interface that may be implemented by a wl_surface, for
++ implementations that provide a desktop-style user interface.
++
++ It provides a base set of functionality required to construct user
++ interface elements requiring management by the compositor, such as
++ toplevel windows, menus, etc. The types of functionality are split into
++ xdg_surface roles.
++
++ Creating an xdg_surface does not set the role for a wl_surface. In order
++ to map an xdg_surface, the client must create a role-specific object
++ using, e.g., get_toplevel, get_popup. The wl_surface for any given
++ xdg_surface can have at most one role, and may not be assigned any role
++ not based on xdg_surface.
++
++ A role must be assigned before any other requests are made to the
++ xdg_surface object.
++
++ The client must call wl_surface.commit on the corresponding wl_surface
++ for the xdg_surface state to take effect.
++
++ Creating an xdg_surface from a wl_surface which has a buffer attached or
++ committed is a client error, and any attempts by a client to attach or
++ manipulate a buffer prior to the first xdg_surface.configure call must
++ also be treated as errors.
++
++ After creating a role-specific object and setting it up, the client must
++ perform an initial commit without any buffer attached. The compositor
++ will reply with an xdg_surface.configure event. The client must
++ acknowledge it and is then allowed to attach a buffer to map the surface.
++
++ Mapping an xdg_surface-based role surface is defined as making it
++ possible for the surface to be shown by the compositor. Note that
++ a mapped surface is not guaranteed to be visible once it is mapped.
++
++ For an xdg_surface to be mapped by the compositor, the following
++ conditions must be met:
++ (1) the client has assigned an xdg_surface-based role to the surface
++ (2) the client has set and committed the xdg_surface state and the
++ role-dependent state to the surface
++ (3) the client has committed a buffer to the surface
++
++ A newly-unmapped surface is considered to have met condition (1) out
++ of the 3 required conditions for mapping a surface if its role surface
++ has not been destroyed, i.e. the client must perform the initial commit
++ again before attaching a buffer.
++ </description>
++
++ <enum name="error">
++ <entry name="not_constructed" value="1"/>
++ <entry name="already_constructed" value="2"/>
++ <entry name="unconfigured_buffer" value="3"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_surface">
++ Destroy the xdg_surface object. An xdg_surface must only be destroyed
++ after its role object has been destroyed.
++ </description>
++ </request>
++
++ <request name="get_toplevel">
++ <description summary="assign the xdg_toplevel surface role">
++ This creates an xdg_toplevel object for the given xdg_surface and gives
++ the associated wl_surface the xdg_toplevel role.
++
++ See the documentation of xdg_toplevel for more details about what an
++ xdg_toplevel is and how it is used.
++ </description>
++ <arg name="id" type="new_id" interface="xdg_toplevel"/>
++ </request>
++
++ <request name="get_popup">
++ <description summary="assign the xdg_popup surface role">
++ This creates an xdg_popup object for the given xdg_surface and gives
++ the associated wl_surface the xdg_popup role.
++
++ If null is passed as a parent, a parent surface must be specified using
++ some other protocol, before committing the initial state.
++
++ See the documentation of xdg_popup for more details about what an
++ xdg_popup is and how it is used.
++ </description>
++ <arg name="id" type="new_id" interface="xdg_popup"/>
++ <arg name="parent" type="object" interface="xdg_surface" allow-null="true"/>
++ <arg name="positioner" type="object" interface="xdg_positioner"/>
++ </request>
++
++ <request name="set_window_geometry">
++ <description summary="set the new window geometry">
++ The window geometry of a surface is its "visible bounds" from the
++ user's perspective. Client-side decorations often have invisible
++ portions like drop-shadows which should be ignored for the
++ purposes of aligning, placing and constraining windows.
++
++ The window geometry is double buffered, and will be applied at the
++ time wl_surface.commit of the corresponding wl_surface is called.
++
++ When maintaining a position, the compositor should treat the (x, y)
++ coordinate of the window geometry as the top left corner of the window.
++ A client changing the (x, y) window geometry coordinate should in
++ general not alter the position of the window.
++
++ Once the window geometry of the surface is set, it is not possible to
++ unset it, and it will remain the same until set_window_geometry is
++ called again, even if a new subsurface or buffer is attached.
++
++ If never set, the value is the full bounds of the surface,
++ including any subsurfaces. This updates dynamically on every
++ commit. This unset is meant for extremely simple clients.
++
++ The arguments are given in the surface-local coordinate space of
++ the wl_surface associated with this xdg_surface.
++
++ The width and height must be greater than zero. Setting an invalid size
++ will raise an error. When applied, the effective window geometry will be
++ the set window geometry clamped to the bounding rectangle of the
++ combined geometry of the surface of the xdg_surface and the associated
++ subsurfaces.
++ </description>
++ <arg name="x" type="int"/>
++ <arg name="y" type="int"/>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ </request>
++
++ <request name="ack_configure">
++ <description summary="ack a configure event">
++ When a configure event is received, if a client commits the
++ surface in response to the configure event, then the client
++ must make an ack_configure request sometime before the commit
++ request, passing along the serial of the configure event.
++
++ For instance, for toplevel surfaces the compositor might use this
++ information to move a surface to the top left only when the client has
++ drawn itself for the maximized or fullscreen state.
++
++ If the client receives multiple configure events before it
++ can respond to one, it only has to ack the last configure event.
++
++ A client is not required to commit immediately after sending
++ an ack_configure request - it may even ack_configure several times
++ before its next surface commit.
++
++ A client may send multiple ack_configure requests before committing, but
++ only the last request sent before a commit indicates which configure
++ event the client really is responding to.
++ </description>
++ <arg name="serial" type="uint" summary="the serial from the configure event"/>
++ </request>
++
++ <event name="configure">
++ <description summary="suggest a surface change">
++ The configure event marks the end of a configure sequence. A configure
++ sequence is a set of one or more events configuring the state of the
++ xdg_surface, including the final xdg_surface.configure event.
++
++ Where applicable, xdg_surface surface roles will during a configure
++ sequence extend this event as a latched state sent as events before the
++ xdg_surface.configure event. Such events should be considered to make up
++ a set of atomically applied configuration states, where the
++ xdg_surface.configure commits the accumulated state.
++
++ Clients should arrange their surface for the new states, and then send
++ an ack_configure request with the serial sent in this configure event at
++ some point before committing the new surface.
++
++ If the client receives multiple configure events before it can respond
++ to one, it is free to discard all but the last event it received.
++ </description>
++ <arg name="serial" type="uint" summary="serial of the configure event"/>
++ </event>
++
++ </interface>
++
++ <interface name="xdg_toplevel" version="5">
++ <description summary="toplevel surface">
++ This interface defines an xdg_surface role which allows a surface to,
++ among other things, set window-like properties such as maximize,
++ fullscreen, and minimize, set application-specific metadata like title and
++ id, and well as trigger user interactive operations such as interactive
++ resize and move.
++
++ Unmapping an xdg_toplevel means that the surface cannot be shown
++ by the compositor until it is explicitly mapped again.
++ All active operations (e.g., move, resize) are canceled and all
++ attributes (e.g. title, state, stacking, ...) are discarded for
++ an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to
++ the state it had right after xdg_surface.get_toplevel. The client
++ can re-map the toplevel by perfoming a commit without any buffer
++ attached, waiting for a configure event and handling it as usual (see
++ xdg_surface description).
++
++ Attaching a null buffer to a toplevel unmaps the surface.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_toplevel">
++ This request destroys the role surface and unmaps the surface;
++ see "Unmapping" behavior in interface section for details.
++ </description>
++ </request>
++
++ <enum name="error">
++ <entry name="invalid_resize_edge" value="0" summary="provided value is
++ not a valid variant of the resize_edge enum"/>
++ </enum>
++
++ <request name="set_parent">
++ <description summary="set the parent of this surface">
++ Set the "parent" of this surface. This surface should be stacked
++ above the parent surface and all other ancestor surfaces.
++
++ Parent surfaces should be set on dialogs, toolboxes, or other
++ "auxiliary" surfaces, so that the parent is raised when the dialog
++ is raised.
++
++ Setting a null parent for a child surface unsets its parent. Setting
++ a null parent for a surface which currently has no parent is a no-op.
++
++ Only mapped surfaces can have child surfaces. Setting a parent which
++ is not mapped is equivalent to setting a null parent. If a surface
++ becomes unmapped, its children's parent is set to the parent of
++ the now-unmapped surface. If the now-unmapped surface has no parent,
++ its children's parent is unset. If the now-unmapped surface becomes
++ mapped again, its parent-child relationship is not restored.
++ </description>
++ <arg name="parent" type="object" interface="xdg_toplevel" allow-null="true"/>
++ </request>
++
++ <request name="set_title">
++ <description summary="set surface title">
++ Set a short title for the surface.
++
++ This string may be used to identify the surface in a task bar,
++ window list, or other user interface elements provided by the
++ compositor.
++
++ The string must be encoded in UTF-8.
++ </description>
++ <arg name="title" type="string"/>
++ </request>
++
++ <request name="set_app_id">
++ <description summary="set application ID">
++ Set an application identifier for the surface.
++
++ The app ID identifies the general class of applications to which
++ the surface belongs. The compositor can use this to group multiple
++ surfaces together, or to determine how to launch a new application.
++
++ For D-Bus activatable applications, the app ID is used as the D-Bus
++ service name.
++
++ The compositor shell will try to group application surfaces together
++ by their app ID. As a best practice, it is suggested to select app
++ ID's that match the basename of the application's .desktop file.
++ For example, "org.freedesktop.FooViewer" where the .desktop file is
++ "org.freedesktop.FooViewer.desktop".
++
++ Like other properties, a set_app_id request can be sent after the
++ xdg_toplevel has been mapped to update the property.
++
++ See the desktop-entry specification [0] for more details on
++ application identifiers and how they relate to well-known D-Bus
++ names and .desktop files.
++
++ [0] http://standards.freedesktop.org/desktop-entry-spec/
++ </description>
++ <arg name="app_id" type="string"/>
++ </request>
++
++ <request name="show_window_menu">
++ <description summary="show the window menu">
++ Clients implementing client-side decorations might want to show
++ a context menu when right-clicking on the decorations, giving the
++ user a menu that they can use to maximize or minimize the window.
++
++ This request asks the compositor to pop up such a window menu at
++ the given position, relative to the local surface coordinates of
++ the parent surface. There are no guarantees as to what menu items
++ the window menu contains.
++
++ This request must be used in response to some sort of user action
++ like a button press, key press, or touch down event.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++ <arg name="serial" type="uint" summary="the serial of the user event"/>
++ <arg name="x" type="int" summary="the x position to pop up the window menu at"/>
++ <arg name="y" type="int" summary="the y position to pop up the window menu at"/>
++ </request>
++
++ <request name="move">
++ <description summary="start an interactive move">
++ Start an interactive, user-driven move of the surface.
++
++ This request must be used in response to some sort of user action
++ like a button press, key press, or touch down event. The passed
++ serial is used to determine the type of interactive move (touch,
++ pointer, etc).
++
++ The server may ignore move requests depending on the state of
++ the surface (e.g. fullscreen or maximized), or if the passed serial
++ is no longer valid.
++
++ If triggered, the surface will lose the focus of the device
++ (wl_pointer, wl_touch, etc) used for the move. It is up to the
++ compositor to visually indicate that the move is taking place, such as
++ updating a pointer cursor, during the move. There is no guarantee
++ that the device focus will return when the move is completed.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++ <arg name="serial" type="uint" summary="the serial of the user event"/>
++ </request>
++
++ <enum name="resize_edge">
++ <description summary="edge values for resizing">
++ These values are used to indicate which edge of a surface
++ is being dragged in a resize operation.
++ </description>
++ <entry name="none" value="0"/>
++ <entry name="top" value="1"/>
++ <entry name="bottom" value="2"/>
++ <entry name="left" value="4"/>
++ <entry name="top_left" value="5"/>
++ <entry name="bottom_left" value="6"/>
++ <entry name="right" value="8"/>
++ <entry name="top_right" value="9"/>
++ <entry name="bottom_right" value="10"/>
++ </enum>
++
++ <request name="resize">
++ <description summary="start an interactive resize">
++ Start a user-driven, interactive resize of the surface.
++
++ This request must be used in response to some sort of user action
++ like a button press, key press, or touch down event. The passed
++ serial is used to determine the type of interactive resize (touch,
++ pointer, etc).
++
++ The server may ignore resize requests depending on the state of
++ the surface (e.g. fullscreen or maximized).
++
++ If triggered, the client will receive configure events with the
++ "resize" state enum value and the expected sizes. See the "resize"
++ enum value for more details about what is required. The client
++ must also acknowledge configure events using "ack_configure". After
++ the resize is completed, the client will receive another "configure"
++ event without the resize state.
++
++ If triggered, the surface also will lose the focus of the device
++ (wl_pointer, wl_touch, etc) used for the resize. It is up to the
++ compositor to visually indicate that the resize is taking place,
++ such as updating a pointer cursor, during the resize. There is no
++ guarantee that the device focus will return when the resize is
++ completed.
++
++ The edges parameter specifies how the surface should be resized, and
++ is one of the values of the resize_edge enum. Values not matching
++ a variant of the enum will cause a protocol error. The compositor
++ may use this information to update the surface position for example
++ when dragging the top left corner. The compositor may also use
++ this information to adapt its behavior, e.g. choose an appropriate
++ cursor image.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++ <arg name="serial" type="uint" summary="the serial of the user event"/>
++ <arg name="edges" type="uint" enum="resize_edge" summary="which edge or corner is being dragged"/>
++ </request>
++
++ <enum name="state">
++ <description summary="types of state on the surface">
++ The different state values used on the surface. This is designed for
++ state values like maximized, fullscreen. It is paired with the
++ configure event to ensure that both the client and the compositor
++ setting the state can be synchronized.
++
++ States set in this way are double-buffered. They will get applied on
++ the next commit.
++ </description>
++ <entry name="maximized" value="1" summary="the surface is maximized">
++ <description summary="the surface is maximized">
++ The surface is maximized. The window geometry specified in the configure
++ event must be obeyed by the client.
++
++ The client should draw without shadow or other
++ decoration outside of the window geometry.
++ </description>
++ </entry>
++ <entry name="fullscreen" value="2" summary="the surface is fullscreen">
++ <description summary="the surface is fullscreen">
++ The surface is fullscreen. The window geometry specified in the
++ configure event is a maximum; the client cannot resize beyond it. For
++ a surface to cover the whole fullscreened area, the geometry
++ dimensions must be obeyed by the client. For more details, see
++ xdg_toplevel.set_fullscreen.
++ </description>
++ </entry>
++ <entry name="resizing" value="3" summary="the surface is being resized">
++ <description summary="the surface is being resized">
++ The surface is being resized. The window geometry specified in the
++ configure event is a maximum; the client cannot resize beyond it.
++ Clients that have aspect ratio or cell sizing configuration can use
++ a smaller size, however.
++ </description>
++ </entry>
++ <entry name="activated" value="4" summary="the surface is now activated">
++ <description summary="the surface is now activated">
++ Client window decorations should be painted as if the window is
++ active. Do not assume this means that the window actually has
++ keyboard or pointer focus.
++ </description>
++ </entry>
++ <entry name="tiled_left" value="5" since="2">
++ <description summary="the surface’s left edge is tiled">
++ The window is currently in a tiled layout and the left edge is
++ considered to be adjacent to another part of the tiling grid.
++ </description>
++ </entry>
++ <entry name="tiled_right" value="6" since="2">
++ <description summary="the surface’s right edge is tiled">
++ The window is currently in a tiled layout and the right edge is
++ considered to be adjacent to another part of the tiling grid.
++ </description>
++ </entry>
++ <entry name="tiled_top" value="7" since="2">
++ <description summary="the surface’s top edge is tiled">
++ The window is currently in a tiled layout and the top edge is
++ considered to be adjacent to another part of the tiling grid.
++ </description>
++ </entry>
++ <entry name="tiled_bottom" value="8" since="2">
++ <description summary="the surface’s bottom edge is tiled">
++ The window is currently in a tiled layout and the bottom edge is
++ considered to be adjacent to another part of the tiling grid.
++ </description>
++ </entry>
++ </enum>
++
++ <request name="set_max_size">
++ <description summary="set the maximum size">
++ Set a maximum size for the window.
++
++ The client can specify a maximum size so that the compositor does
++ not try to configure the window beyond this size.
++
++ The width and height arguments are in window geometry coordinates.
++ See xdg_surface.set_window_geometry.
++
++ Values set in this way are double-buffered. They will get applied
++ on the next commit.
++
++ The compositor can use this information to allow or disallow
++ different states like maximize or fullscreen and draw accurate
++ animations.
++
++ Similarly, a tiling window manager may use this information to
++ place and resize client windows in a more effective way.
++
++ The client should not rely on the compositor to obey the maximum
++ size. The compositor may decide to ignore the values set by the
++ client and request a larger size.
++
++ If never set, or a value of zero in the request, means that the
++ client has no expected maximum size in the given dimension.
++ As a result, a client wishing to reset the maximum size
++ to an unspecified state can use zero for width and height in the
++ request.
++
++ Requesting a maximum size to be smaller than the minimum size of
++ a surface is illegal and will result in a protocol error.
++
++ The width and height must be greater than or equal to zero. Using
++ strictly negative values for width and height will result in a
++ protocol error.
++ </description>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ </request>
++
++ <request name="set_min_size">
++ <description summary="set the minimum size">
++ Set a minimum size for the window.
++
++ The client can specify a minimum size so that the compositor does
++ not try to configure the window below this size.
++
++ The width and height arguments are in window geometry coordinates.
++ See xdg_surface.set_window_geometry.
++
++ Values set in this way are double-buffered. They will get applied
++ on the next commit.
++
++ The compositor can use this information to allow or disallow
++ different states like maximize or fullscreen and draw accurate
++ animations.
++
++ Similarly, a tiling window manager may use this information to
++ place and resize client windows in a more effective way.
++
++ The client should not rely on the compositor to obey the minimum
++ size. The compositor may decide to ignore the values set by the
++ client and request a smaller size.
++
++ If never set, or a value of zero in the request, means that the
++ client has no expected minimum size in the given dimension.
++ As a result, a client wishing to reset the minimum size
++ to an unspecified state can use zero for width and height in the
++ request.
++
++ Requesting a minimum size to be larger than the maximum size of
++ a surface is illegal and will result in a protocol error.
++
++ The width and height must be greater than or equal to zero. Using
++ strictly negative values for width and height will result in a
++ protocol error.
++ </description>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ </request>
++
++ <request name="set_maximized">
++ <description summary="maximize the window">
++ Maximize the surface.
++
++ After requesting that the surface should be maximized, the compositor
++ will respond by emitting a configure event. Whether this configure
++ actually sets the window maximized is subject to compositor policies.
++ The client must then update its content, drawing in the configured
++ state. The client must also acknowledge the configure when committing
++ the new content (see ack_configure).
++
++ It is up to the compositor to decide how and where to maximize the
++ surface, for example which output and what region of the screen should
++ be used.
++
++ If the surface was already maximized, the compositor will still emit
++ a configure event with the "maximized" state.
++
++ If the surface is in a fullscreen state, this request has no direct
++ effect. It may alter the state the surface is returned to when
++ unmaximized unless overridden by the compositor.
++ </description>
++ </request>
++
++ <request name="unset_maximized">
++ <description summary="unmaximize the window">
++ Unmaximize the surface.
++
++ After requesting that the surface should be unmaximized, the compositor
++ will respond by emitting a configure event. Whether this actually
++ un-maximizes the window is subject to compositor policies.
++ If available and applicable, the compositor will include the window
++ geometry dimensions the window had prior to being maximized in the
++ configure event. The client must then update its content, drawing it in
++ the configured state. The client must also acknowledge the configure
++ when committing the new content (see ack_configure).
++
++ It is up to the compositor to position the surface after it was
++ unmaximized; usually the position the surface had before maximizing, if
++ applicable.
++
++ If the surface was already not maximized, the compositor will still
++ emit a configure event without the "maximized" state.
++
++ If the surface is in a fullscreen state, this request has no direct
++ effect. It may alter the state the surface is returned to when
++ unmaximized unless overridden by the compositor.
++ </description>
++ </request>
++
++ <request name="set_fullscreen">
++ <description summary="set the window as fullscreen on an output">
++ Make the surface fullscreen.
++
++ After requesting that the surface should be fullscreened, the
++ compositor will respond by emitting a configure event. Whether the
++ client is actually put into a fullscreen state is subject to compositor
++ policies. The client must also acknowledge the configure when
++ committing the new content (see ack_configure).
++
++ The output passed by the request indicates the client's preference as
++ to which display it should be set fullscreen on. If this value is NULL,
++ it's up to the compositor to choose which display will be used to map
++ this surface.
++
++ If the surface doesn't cover the whole output, the compositor will
++ position the surface in the center of the output and compensate with
++ with border fill covering the rest of the output. The content of the
++ border fill is undefined, but should be assumed to be in some way that
++ attempts to blend into the surrounding area (e.g. solid black).
++
++ If the fullscreened surface is not opaque, the compositor must make
++ sure that other screen content not part of the same surface tree (made
++ up of subsurfaces, popups or similarly coupled surfaces) are not
++ visible below the fullscreened surface.
++ </description>
++ <arg name="output" type="object" interface="wl_output" allow-null="true"/>
++ </request>
++
++ <request name="unset_fullscreen">
++ <description summary="unset the window as fullscreen">
++ Make the surface no longer fullscreen.
++
++ After requesting that the surface should be unfullscreened, the
++ compositor will respond by emitting a configure event.
++ Whether this actually removes the fullscreen state of the client is
++ subject to compositor policies.
++
++ Making a surface unfullscreen sets states for the surface based on the following:
++ * the state(s) it may have had before becoming fullscreen
++ * any state(s) decided by the compositor
++ * any state(s) requested by the client while the surface was fullscreen
++
++ The compositor may include the previous window geometry dimensions in
++ the configure event, if applicable.
++
++ The client must also acknowledge the configure when committing the new
++ content (see ack_configure).
++ </description>
++ </request>
++
++ <request name="set_minimized">
++ <description summary="set the window as minimized">
++ Request that the compositor minimize your surface. There is no
++ way to know if the surface is currently minimized, nor is there
++ any way to unset minimization on this surface.
++
++ If you are looking to throttle redrawing when minimized, please
++ instead use the wl_surface.frame event for this, as this will
++ also work with live previews on windows in Alt-Tab, Expose or
++ similar compositor features.
++ </description>
++ </request>
++
++ <event name="configure">
++ <description summary="suggest a surface change">
++ This configure event asks the client to resize its toplevel surface or
++ to change its state. The configured state should not be applied
++ immediately. See xdg_surface.configure for details.
++
++ The width and height arguments specify a hint to the window
++ about how its surface should be resized in window geometry
++ coordinates. See set_window_geometry.
++
++ If the width or height arguments are zero, it means the client
++ should decide its own window dimension. This may happen when the
++ compositor needs to configure the state of the surface but doesn't
++ have any information about any previous or expected dimension.
++
++ The states listed in the event specify how the width/height
++ arguments should be interpreted, and possibly how it should be
++ drawn.
++
++ Clients must send an ack_configure in response to this event. See
++ xdg_surface.configure and xdg_surface.ack_configure for details.
++ </description>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ <arg name="states" type="array"/>
++ </event>
++
++ <event name="close">
++ <description summary="surface wants to be closed">
++ The close event is sent by the compositor when the user
++ wants the surface to be closed. This should be equivalent to
++ the user clicking the close button in client-side decorations,
++ if your application has any.
++
++ This is only a request that the user intends to close the
++ window. The client may choose to ignore this request, or show
++ a dialog to ask the user to save their data, etc.
++ </description>
++ </event>
++
++ <!-- Version 4 additions -->
++
++ <event name="configure_bounds" since="4">
++ <description summary="recommended window geometry bounds">
++ The configure_bounds event may be sent prior to a xdg_toplevel.configure
++ event to communicate the bounds a window geometry size is recommended
++ to constrain to.
++
++ The passed width and height are in surface coordinate space. If width
++ and height are 0, it means bounds is unknown and equivalent to as if no
++ configure_bounds event was ever sent for this surface.
++
++ The bounds can for example correspond to the size of a monitor excluding
++ any panels or other shell components, so that a surface isn't created in
++ a way that it cannot fit.
++
++ The bounds may change at any point, and in such a case, a new
++ xdg_toplevel.configure_bounds will be sent, followed by
++ xdg_toplevel.configure and xdg_surface.configure.
++ </description>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ </event>
++
++ <!-- Version 5 additions -->
++
++ <enum name="wm_capabilities" since="5">
++ <entry name="window_menu" value="1" summary="show_window_menu is available"/>
++ <entry name="maximize" value="2" summary="set_maximized and unset_maximized are available"/>
++ <entry name="fullscreen" value="3" summary="set_fullscreen and unset_fullscreen are available"/>
++ <entry name="minimize" value="4" summary="set_minimized is available"/>
++ </enum>
++
++ <event name="wm_capabilities" since="5">
++ <description summary="compositor capabilities">
++ This event advertises the capabilities supported by the compositor. If
++ a capability isn't supported, clients should hide or disable the UI
++ elements that expose this functionality. For instance, if the
++ compositor doesn't advertise support for minimized toplevels, a button
++ triggering the set_minimized request should not be displayed.
++
++ The compositor will ignore requests it doesn't support. For instance,
++ a compositor which doesn't advertise support for minimized will ignore
++ set_minimized requests.
++
++ Compositors must send this event once before the first
++ xdg_surface.configure event. When the capabilities change, compositors
++ must send this event again and then send an xdg_surface.configure
++ event.
++
++ The configured state should not be applied immediately. See
++ xdg_surface.configure for details.
++
++ The capabilities are sent as an array of 32-bit unsigned integers in
++ native endianness.
++ </description>
++ <arg name="capabilities" type="array" summary="array of 32-bit capabilities"/>
++ </event>
++ </interface>
++
++ <interface name="xdg_popup" version="5">
++ <description summary="short-lived, popup surfaces for menus">
++ A popup surface is a short-lived, temporary surface. It can be used to
++ implement for example menus, popovers, tooltips and other similar user
++ interface concepts.
++
++ A popup can be made to take an explicit grab. See xdg_popup.grab for
++ details.
++
++ When the popup is dismissed, a popup_done event will be sent out, and at
++ the same time the surface will be unmapped. See the xdg_popup.popup_done
++ event for details.
++
++ Explicitly destroying the xdg_popup object will also dismiss the popup and
++ unmap the surface. Clients that want to dismiss the popup when another
++ surface of their own is clicked should dismiss the popup using the destroy
++ request.
++
++ A newly created xdg_popup will be stacked on top of all previously created
++ xdg_popup surfaces associated with the same xdg_toplevel.
++
++ The parent of an xdg_popup must be mapped (see the xdg_surface
++ description) before the xdg_popup itself.
++
++ The client must call wl_surface.commit on the corresponding wl_surface
++ for the xdg_popup state to take effect.
++ </description>
++
++ <enum name="error">
++ <entry name="invalid_grab" value="0"
++ summary="tried to grab after being mapped"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="remove xdg_popup interface">
++ This destroys the popup. Explicitly destroying the xdg_popup
++ object will also dismiss the popup, and unmap the surface.
++
++ If this xdg_popup is not the "topmost" popup, a protocol error
++ will be sent.
++ </description>
++ </request>
++
++ <request name="grab">
++ <description summary="make the popup take an explicit grab">
++ This request makes the created popup take an explicit grab. An explicit
++ grab will be dismissed when the user dismisses the popup, or when the
++ client destroys the xdg_popup. This can be done by the user clicking
++ outside the surface, using the keyboard, or even locking the screen
++ through closing the lid or a timeout.
++
++ If the compositor denies the grab, the popup will be immediately
++ dismissed.
++
++ This request must be used in response to some sort of user action like a
++ button press, key press, or touch down event. The serial number of the
++ event should be passed as 'serial'.
++
++ The parent of a grabbing popup must either be an xdg_toplevel surface or
++ another xdg_popup with an explicit grab. If the parent is another
++ xdg_popup it means that the popups are nested, with this popup now being
++ the topmost popup.
++
++ Nested popups must be destroyed in the reverse order they were created
++ in, e.g. the only popup you are allowed to destroy at all times is the
++ topmost one.
++
++ When compositors choose to dismiss a popup, they may dismiss every
++ nested grabbing popup as well. When a compositor dismisses popups, it
++ will follow the same dismissing order as required from the client.
++
++ If the topmost grabbing popup is destroyed, the grab will be returned to
++ the parent of the popup, if that parent previously had an explicit grab.
++
++ If the parent is a grabbing popup which has already been dismissed, this
++ popup will be immediately dismissed. If the parent is a popup that did
++ not take an explicit grab, an error will be raised.
++
++ During a popup grab, the client owning the grab will receive pointer
++ and touch events for all their surfaces as normal (similar to an
++ "owner-events" grab in X11 parlance), while the top most grabbing popup
++ will always have keyboard focus.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat"
++ summary="the wl_seat of the user event"/>
++ <arg name="serial" type="uint" summary="the serial of the user event"/>
++ </request>
++
++ <event name="configure">
++ <description summary="configure the popup surface">
++ This event asks the popup surface to configure itself given the
++ configuration. The configured state should not be applied immediately.
++ See xdg_surface.configure for details.
++
++ The x and y arguments represent the position the popup was placed at
++ given the xdg_positioner rule, relative to the upper left corner of the
++ window geometry of the parent surface.
++
++ For version 2 or older, the configure event for an xdg_popup is only
++ ever sent once for the initial configuration. Starting with version 3,
++ it may be sent again if the popup is setup with an xdg_positioner with
++ set_reactive requested, or in response to xdg_popup.reposition requests.
++ </description>
++ <arg name="x" type="int"
++ summary="x position relative to parent surface window geometry"/>
++ <arg name="y" type="int"
++ summary="y position relative to parent surface window geometry"/>
++ <arg name="width" type="int" summary="window geometry width"/>
++ <arg name="height" type="int" summary="window geometry height"/>
++ </event>
++
++ <event name="popup_done">
++ <description summary="popup interaction is done">
++ The popup_done event is sent out when a popup is dismissed by the
++ compositor. The client should destroy the xdg_popup object at this
++ point.
++ </description>
++ </event>
++
++ <!-- Version 3 additions -->
++
++ <request name="reposition" since="3">
++ <description summary="recalculate the popup's location">
++ Reposition an already-mapped popup. The popup will be placed given the
++ details in the passed xdg_positioner object, and a
++ xdg_popup.repositioned followed by xdg_popup.configure and
++ xdg_surface.configure will be emitted in response. Any parameters set
++ by the previous positioner will be discarded.
++
++ The passed token will be sent in the corresponding
++ xdg_popup.repositioned event. The new popup position will not take
++ effect until the corresponding configure event is acknowledged by the
++ client. See xdg_popup.repositioned for details. The token itself is
++ opaque, and has no other special meaning.
++
++ If multiple reposition requests are sent, the compositor may skip all
++ but the last one.
++
++ If the popup is repositioned in response to a configure event for its
++ parent, the client should send an xdg_positioner.set_parent_configure
++ and possibly an xdg_positioner.set_parent_size request to allow the
++ compositor to properly constrain the popup.
++
++ If the popup is repositioned together with a parent that is being
++ resized, but not in response to a configure event, the client should
++ send an xdg_positioner.set_parent_size request.
++ </description>
++ <arg name="positioner" type="object" interface="xdg_positioner"/>
++ <arg name="token" type="uint" summary="reposition request token"/>
++ </request>
++
++ <event name="repositioned" since="3">
++ <description summary="signal the completion of a repositioned request">
++ The repositioned event is sent as part of a popup configuration
++ sequence, together with xdg_popup.configure and lastly
++ xdg_surface.configure to notify the completion of a reposition request.
++
++ The repositioned event is to notify about the completion of a
++ xdg_popup.reposition request. The token argument is the token passed
++ in the xdg_popup.reposition request.
++
++ Immediately after this event is emitted, xdg_popup.configure and
++ xdg_surface.configure will be sent with the updated size and position,
++ as well as a new configure serial.
++
++ The client should optionally update the content of the popup, but must
++ acknowledge the new popup configuration for the new position to take
++ effect. See xdg_surface.ack_configure for details.
++ </description>
++ <arg name="token" type="uint" summary="reposition request token"/>
++ </event>
++
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++Linux DRM lease
++
++Maintainers:
++Drew DeVault <sir@cmpwn.com>
++Marius Vlad <marius.vlad@collabora.com>
++Xaver Hugl <xaver.hugl@gmail.com>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="drm_lease_v1">
++ <copyright>
++ Copyright © 2018 NXP
++ Copyright © 2019 Status Research & Development GmbH.
++ Copyright © 2021 Xaver Hugl
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="wp_drm_lease_device_v1" version="1">
++ <description summary="lease device">
++ This protocol is used by Wayland compositors which act as Direct
++ Renderering Manager (DRM) masters to lease DRM resources to Wayland
++ clients.
++
++ The compositor will advertise one wp_drm_lease_device_v1 global for each
++ DRM node. Some time after a client binds to the wp_drm_lease_device_v1
++ global, the compositor will send a drm_fd event followed by zero, one or
++ more connector events. After all currently available connectors have been
++ sent, the compositor will send a wp_drm_lease_device_v1.done event.
++
++ When the list of connectors available for lease changes the compositor
++ will send wp_drm_lease_device_v1.connector events for added connectors and
++ wp_drm_lease_connector_v1.withdrawn events for removed connectors,
++ followed by a wp_drm_lease_device_v1.done event.
++
++ The compositor will indicate when a device is gone by removing the global
++ via a wl_registry.global_remove event. Upon receiving this event, the
++ client should destroy any matching wp_drm_lease_device_v1 object.
++
++ To destroy a wp_drm_lease_device_v1 object, the client must first issue
++ a release request. Upon receiving this request, the compositor will
++ immediately send a released event and destroy the object. The client must
++ continue to process and discard drm_fd and connector events until it
++ receives the released event. Upon receiving the released event, the
++ client can safely cleanup any client-side resources.
++
++ Warning! The protocol described in this file is currently in the testing
++ phase. Backward compatible changes may be added together with the
++ corresponding interface version bump. Backward incompatible changes can
++ only be done by creating a new major version of the extension.
++ </description>
++
++ <request name="create_lease_request">
++ <description summary="create a lease request object">
++ Creates a lease request object.
++
++ See the documentation for wp_drm_lease_request_v1 for details.
++ </description>
++ <arg name="id" type="new_id" interface="wp_drm_lease_request_v1" />
++ </request>
++
++ <request name="release">
++ <description summary="release this object">
++ Indicates the client no longer wishes to use this object. In response
++ the compositor will immediately send the released event and destroy
++ this object. It can however not guarantee that the client won't receive
++ connector events before the released event. The client must not send any
++ requests after this one, doing so will raise a wl_display error.
++ Existing connectors, lease request and leases will not be affected.
++ </description>
++ </request>
++
++ <event name="drm_fd">
++ <description summary="open a non-master fd for this DRM node">
++ The compositor will send this event when the wp_drm_lease_device_v1
++ global is bound, although there are no guarantees as to how long this
++ takes - the compositor might need to wait until regaining DRM master.
++ The included fd is a non-master DRM file descriptor opened for this
++ device and the compositor must not authenticate it.
++ The purpose of this event is to give the client the ability to
++ query DRM and discover information which may help them pick the
++ appropriate DRM device or select the appropriate connectors therein.
++ </description>
++ <arg name="fd" type="fd" summary="DRM file descriptor" />
++ </event>
++
++ <event name="connector">
++ <description summary="advertise connectors available for leases">
++ The compositor will use this event to advertise connectors available for
++ lease by clients. This object may be passed into a lease request to
++ indicate the client would like to lease that connector, see
++ wp_drm_lease_request_v1.request_connector for details. While the
++ compositor will make a best effort to not send disconnected connectors,
++ no guarantees can be made.
++
++ The compositor must send the drm_fd event before sending connectors.
++ After the drm_fd event it will send all available connectors but may
++ send additional connectors at any time.
++ </description>
++ <arg name="id" type="new_id" interface="wp_drm_lease_connector_v1" />
++ </event>
++
++ <event name="done">
++ <description summary="signals grouping of connectors">
++ The compositor will send this event to indicate that it has sent all
++ currently available connectors after the client binds to the global or
++ when it updates the connector list, for example on hotplug, drm master
++ change or when a leased connector becomes available again. It will
++ similarly send this event to group wp_drm_lease_connector_v1.withdrawn
++ events of connectors of this device.
++ </description>
++ </event>
++
++ <event name="released" type="destructor">
++ <description summary="the compositor has finished using the device">
++ This event is sent in response to the release request and indicates
++ that the compositor is done sending connector events.
++ The compositor will destroy this object immediately after sending the
++ event and it will become invalid. The client should release any
++ resources associated with this device after receiving this event.
++ </description>
++ </event>
++ </interface>
++
++ <interface name="wp_drm_lease_connector_v1" version="1">
++ <description summary="a leasable DRM connector">
++ Represents a DRM connector which is available for lease. These objects are
++ created via wp_drm_lease_device_v1.connector events, and should be passed
++ to lease requests via wp_drm_lease_request_v1.request_connector.
++ Immediately after the wp_drm_lease_connector_v1 object is created the
++ compositor will send a name, a description, a connector_id and a done
++ event. When the description is updated the compositor will send a
++ description event followed by a done event.
++ </description>
++
++ <event name="name">
++ <description summary="name">
++ The compositor sends this event once the connector is created to
++ indicate the name of this connector. This will not change for the
++ duration of the Wayland session, but is not guaranteed to be consistent
++ between sessions.
++ </description>
++ <arg name="name" type="string" summary="connector name" />
++ </event>
++
++ <event name="description">
++ <description summary="description">
++ The compositor sends this event once the connector is created to provide
++ a human-readable description for this connector, which may be presented
++ to the user. The compositor may send this event multiple times over the
++ lifetime of this object to reflect changes in the description.
++ </description>
++ <arg name="description" type="string" summary="connector description" />
++ </event>
++
++ <event name="connector_id">
++ <description summary="connector_id">
++ The compositor sends this event once the connector is created to
++ indicate the DRM object ID which represents the underlying connector
++ that is being offered. Note that the final lease may include additional
++ object IDs, such as CRTCs and planes.
++ </description>
++ <arg name="connector_id" type="uint" summary="DRM connector ID" />
++ </event>
++
++ <event name="done">
++ <description summary="all properties have been sent">
++ This event is sent after all properties of a connector have been sent.
++ This allows changes to the properties to be seen as atomic even if they
++ happen via multiple events.
++ </description>
++ </event>
++
++ <event name="withdrawn">
++ <description summary="lease offer withdrawn">
++ Sent to indicate that the compositor will no longer honor requests for
++ DRM leases which include this connector. The client may still issue a
++ lease request including this connector, but the compositor will send
++ wp_drm_lease_v1.finished without issuing a lease fd. Compositors are
++ encouraged to send this event when they lose access to connector, for
++ example when the connector is hot-unplugged, when the connector gets
++ leased to a client or when the compositor loses DRM master.
++ </description>
++ </event>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy connector">
++ The client may send this request to indicate that it will not use this
++ connector. Clients are encouraged to send this after receiving the
++ "withdrawn" event so that the server can release the resources
++ associated with this connector offer. Neither existing lease requests
++ nor leases will be affected.
++ </description>
++ </request>
++ </interface>
++
++ <interface name="wp_drm_lease_request_v1" version="1">
++ <description summary="DRM lease request">
++ A client that wishes to lease DRM resources will attach the list of
++ connectors advertised with wp_drm_lease_device_v1.connector that they
++ wish to lease, then use wp_drm_lease_request_v1.submit to submit the
++ request.
++ </description>
++
++ <enum name="error">
++ <entry name="wrong_device" value="0"
++ summary="requested a connector from a different lease device"/>
++ <entry name="duplicate_connector" value="1"
++ summary="requested a connector twice"/>
++ <entry name="empty_lease" value="2"
++ summary="requested a lease without requesting a connector"/>
++ </enum>
++
++ <request name="request_connector">
++ <description summary="request a connector for this lease">
++ Indicates that the client would like to lease the given connector.
++ This is only used as a suggestion, the compositor may choose to
++ include any resources in the lease it issues, or change the set of
++ leased resources at any time. Compositors are however encouraged to
++ include the requested connector and other resources necessary
++ to drive the connected output in the lease.
++
++ Requesting a connector that was created from a different lease device
++ than this lease request raises the wrong_device error. Requesting a
++ connector twice will raise the duplicate_connector error.
++ </description>
++ <arg name="connector" type="object"
++ interface="wp_drm_lease_connector_v1" />
++ </request>
++
++ <request name="submit" type="destructor">
++ <description summary="submit the lease request">
++ Submits the lease request and creates a new wp_drm_lease_v1 object.
++ After calling submit the compositor will immediately destroy this
++ object, issuing any more requests will cause a wl_diplay error.
++ The compositor doesn't make any guarantees about the events of the
++ lease object, clients cannot expect an immediate response.
++ Not requesting any connectors before submitting the lease request
++ will raise the empty_lease error.
++ </description>
++ <arg name="id" type="new_id" interface="wp_drm_lease_v1" />
++ </request>
++ </interface>
++
++ <interface name="wp_drm_lease_v1" version="1">
++ <description summary="a DRM lease">
++ A DRM lease object is used to transfer the DRM file descriptor to the
++ client and manage the lifetime of the lease.
++
++ Some time after the wp_drm_lease_v1 object is created, the compositor
++ will reply with the lease request's result. If the lease request is
++ granted, the compositor will send a lease_fd event. If the lease request
++ is denied, the compositor will send a finished event without a lease_fd
++ event.
++ </description>
++
++ <event name="lease_fd">
++ <description summary="shares the DRM file descriptor">
++ This event returns a file descriptor suitable for use with DRM-related
++ ioctls. The client should use drmModeGetLease to enumerate the DRM
++ objects which have been leased to them. The compositor guarantees it
++ will not use the leased DRM objects itself until it sends the finished
++ event. If the compositor cannot or will not grant a lease for the
++ requested connectors, it will not send this event, instead sending the
++ finished event.
++
++ The compositor will send this event at most once during this objects
++ lifetime.
++ </description>
++ <arg name="leased_fd" type="fd" summary="leased DRM file descriptor" />
++ </event>
++
++ <event name="finished">
++ <description summary="sent when the lease has been revoked">
++ The compositor uses this event to either reject a lease request, or if
++ it previously sent a lease_fd, to notify the client that the lease has
++ been revoked. If the client requires a new lease, they should destroy
++ this object and submit a new lease request. The compositor will send
++ no further events for this object after sending the finish event.
++ Compositors should revoke the lease when any of the leased resources
++ become unavailable, namely when a hot-unplug occurs or when the
++ compositor loses DRM master.
++ </description>
++ </event>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroys the lease object">
++ The client should send this to indicate that it no longer wishes to use
++ this lease. The compositor should use drmModeRevokeLease on the
++ appropriate file descriptor, if necessary.
++ </description>
++ </request>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++ext session lock protocol
++
++Maintainers:
++Isaac Freund <mail@isaacfreund.com>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="ext_session_lock_v1">
++ <copyright>
++ Copyright 2021 Isaac Freund
++
++ Permission to use, copy, modify, and/or distribute this software for any
++ purpose with or without fee is hereby granted, provided that the above
++ copyright notice and this permission notice appear in all copies.
++
++ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ </copyright>
++
++ <description summary="secure session locking with arbitrary graphics">
++ This protocol allows for a privileged Wayland client to lock the session
++ and display arbitrary graphics while the session is locked.
++
++ The compositor may choose to restrict this protocol to a special client
++ launched by the compositor itself or expose it to all privileged clients,
++ this is compositor policy.
++
++ The client is responsible for performing authentication and informing the
++ compositor when the session should be unlocked. If the client dies while
++ the session is locked the session remains locked, possibly permanently
++ depending on compositor policy.
++
++ Warning! The protocol described in this file is currently in the
++ testing phase. Backward compatible changes may be added together with
++ the corresponding interface version bump. Backward incompatible changes
++ can only be done by creating a new major version of the extension.
++ </description>
++
++ <interface name="ext_session_lock_manager_v1" version="1">
++ <description summary="used to lock the session">
++ This interface is used to request that the session be locked.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the session lock manager object">
++ This informs the compositor that the session lock manager object will
++ no longer be used. Existing objects created through this interface
++ remain valid.
++ </description>
++ </request>
++
++ <request name="lock">
++ <description summary="attempt to lock the session">
++ This request creates a session lock and asks the compositor to lock the
++ session. The compositor will send either the ext_session_lock_v1.locked
++ or ext_session_lock_v1.finished event on the created object in
++ response to this request.
++ </description>
++ <arg name="id" type="new_id" interface="ext_session_lock_v1"/>
++ </request>
++ </interface>
++
++ <interface name="ext_session_lock_v1" version="1">
++ <description summary="manage lock state and create lock surfaces">
++ On creation of this object either the locked or finished event will
++ immediately be sent.
++
++ The locked event indicates that the session is locked. This means that
++ the compositor should stop rendering and providing input to normal
++ clients. Instead the compositor should blank all outputs with an opaque
++ color such that their normal content is fully hidden.
++
++ The only surfaces that should be rendered while the session is locked
++ are the lock surfaces created through this interface and optionally,
++ at the compositor's discretion, special privileged surfaces such as
++ input methods or portions of desktop shell UIs.
++
++ If the client dies while the session is locked, the compositor should not
++ unlock the session in response. It is acceptable for the session to be
++ permanently locked if this happens. The compositor may choose to continue
++ to display the lock surfaces the client had mapped before it died or
++ alternatively fall back to a solid color, this is compositor policy.
++
++ Compositors may also allow a secure way to recover the session, the
++ details of this are compositor policy. Compositors may allow a new
++ client to create a ext_session_lock_v1 object and take responsibility
++ for unlocking the session, they may even start a new lock client
++ instance automatically.
++ </description>
++
++ <enum name="error">
++ <entry name="invalid_destroy" value="0"
++ summary="attempted to destroy session lock while locked"/>
++ <entry name="invalid_unlock" value="1"
++ summary="unlock requested but locked event was never sent"/>
++ <entry name="role" value="2"
++ summary="given wl_surface already has a role"/>
++ <entry name="duplicate_output" value="3"
++ summary="given output already has a lock surface"/>
++ <entry name="already_constructed" value="4"
++ summary="given wl_surface has a buffer attached or committed"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the session lock">
++ This informs the compositor that the lock object will no longer be
++ used. Existing objects created through this interface remain valid.
++
++ After this request is made, lock surfaces created through this object
++ should be destroyed by the client as they will no longer be used by
++ the compositor.
++
++ It is a protocol error to make this request if the locked event was
++ sent, the unlock_and_destroy request must be used instead.
++ </description>
++ </request>
++
++ <event name="locked">
++ <description summary="session successfully locked">
++ This client is now responsible for displaying graphics while the
++ session is locked and deciding when to unlock the session.
++
++ Either this event or the finished event will be sent immediately on
++ creation of this object.
++
++ If this event is sent, making the destroy request is a protocol error,
++ the lock object may only be destroyed using the unlock_and_destroy
++ request.
++ </description>
++ </event>
++
++ <event name="finished">
++ <description summary="the session lock object should be destroyed">
++ The compositor has decided that the session lock should be
++ destroyed. Exactly when this event is sent is compositor policy, but
++ it will never be sent more than once for a given session lock object.
++
++ This might be sent because there is already another ext_session_lock_v1
++ object held by a client, or the compositor has decided to deny the
++ request to lock the session for some other reason. This might also
++ be sent because the compositor implements some alternative, secure
++ way to authenticate and unlock the session.
++
++ Either this event or the locked event will be sent exactly once on
++ creation of this object. If the locked event is sent on creation of
++ this object, the finished event may still be sent at some later time
++ in this object's lifetime, this is compositor policy.
++
++ Upon receiving this event, the client should make either the destroy
++ request or the unlock_and_destroy request, depending on whether or
++ not the locked event was received on this object.
++ </description>
++ </event>
++
++ <request name="get_lock_surface">
++ <description summary="create a lock surface for a given output">
++ The client is expected to create lock surfaces for all outputs
++ currently present and any new outputs as they are advertised. These
++ won't be displayed by the compositor unless the lock is successful
++ and the locked event is sent.
++
++ Providing a wl_surface which already has a role or already has a buffer
++ attached or committed is a protocol error, as is attaching/committing
++ a buffer before the first ext_session_lock_surface_v1.configure event.
++
++ Attempting to create more than one lock surface for a given output
++ is a duplicate_output protocol error.
++ </description>
++ <arg name="id" type="new_id" interface="ext_session_lock_surface_v1"/>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ <arg name="output" type="object" interface="wl_output"/>
++ </request>
++
++ <request name="unlock_and_destroy" type="destructor">
++ <description summary="unlock the session, destroying the object">
++ This request indicates that the session should be unlocked, for
++ example because the user has entered their password and it has been
++ verified by the client.
++
++ This request also informs the compositor that the lock object will
++ no longer be used and may be safely destroyed. Existing objects
++ created through this interface remain valid.
++
++ After this request is made, lock surfaces created through this object
++ should be destroyed by the client as they will no longer be used by
++ the compositor.
++
++ It is a protocol error to make this request if the locked event has
++ not been sent. In that case, the lock object may only be destroyed
++ using the destroy request.
++ </description>
++ </request>
++ </interface>
++
++ <interface name="ext_session_lock_surface_v1" version="1">
++ <description summary="a surface displayed while the session is locked">
++ The client may use lock surfaces to display a screensaver, render a
++ dialog to enter a password and unlock the session, or however else it
++ sees fit.
++
++ On binding this interface the compositor will immediately send the
++ first configure event. After making the ack_configure request in
++ response to this event the client may attach and commit the first
++ buffer. Committing the surface before acking the first configure is a
++ protocol error. Committing the surface with a null buffer at any time
++ is a protocol error.
++
++ The compositor is free to handle keyboard/pointer focus for lock
++ surfaces however it chooses. A reasonable way to do this would be to
++ give the first lock surface created keyboard focus and change keyboard
++ focus if the user clicks on other surfaces.
++ </description>
++
++ <enum name="error">
++ <entry name="commit_before_first_ack" value="0"
++ summary="surface committed before first ack_configure request"/>
++ <entry name="null_buffer" value="1"
++ summary="surface committed with a null buffer"/>
++ <entry name="dimensions_mismatch" value="2"
++ summary="failed to match ack'd width/height"/>
++ <entry name="invalid_serial" value="3"
++ summary="serial provided in ack_configure is invalid"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the lock surface object">
++ This informs the compositor that the lock surface object will no
++ longer be used.
++
++ It is recommended for a lock client to destroy lock surfaces if
++ their corresponding wl_output global is removed.
++
++ If a lock surface on an active output is destroyed before the
++ ext_session_lock_v1.unlock_and_destroy event is sent, the compositor
++ must fall back to rendering a solid color.
++ </description>
++ </request>
++
++ <request name="ack_configure">
++ <description summary="ack a configure event">
++ When a configure event is received, if a client commits the surface
++ in response to the configure event, then the client must make an
++ ack_configure request sometime before the commit request, passing
++ along the serial of the configure event.
++
++ If the client receives multiple configure events before it can
++ respond to one, it only has to ack the last configure event.
++
++ A client is not required to commit immediately after sending an
++ ack_configure request - it may even ack_configure several times
++ before its next surface commit.
++
++ A client may send multiple ack_configure requests before committing,
++ but only the last request sent before a commit indicates which
++ configure event the client really is responding to.
++
++ Sending an ack_configure request consumes the configure event
++ referenced by the given serial, as well as all older configure events
++ sent on this object.
++
++ It is a protocol error to issue multiple ack_configure requests
++ referencing the same configure event or to issue an ack_configure
++ request referencing a configure event older than the last configure
++ event acked for a given lock surface.
++ </description>
++ <arg name="serial" type="uint" summary="serial from the configure event"/>
++ </request>
++
++ <event name="configure">
++ <description summary="the client should resize its surface">
++ This event is sent once on binding the interface and may be sent again
++ at the compositor's discretion, for example if output geometry changes.
++
++ The width and height are in surface-local coordinates and are exact
++ requirements. Failing to match these surface dimensions in the next
++ commit after acking a configure is a protocol error.
++ </description>
++ <arg name="serial" type="uint" summary="serial for use in ack_configure"/>
++ <arg name="width" type="uint"/>
++ <arg name="height" type="uint"/>
++ </event>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++Single-pixel buffer protocol
++
++Maintainers:
++Simon Ser <contact@emersion.fr>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="single_pixel_buffer_v1">
++ <copyright>
++ Copyright © 2022 Simon Ser
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <description summary="single pixel buffer factory">
++ This protocol extension allows clients to create single-pixel buffers.
++
++ Compositors supporting this protocol extension should also support the
++ viewporter protocol extension. Clients may use viewporter to scale a
++ single-pixel buffer to a desired size.
++
++ Warning! The protocol described in this file is currently in the testing
++ phase. Backward compatible changes may be added together with the
++ corresponding interface version bump. Backward incompatible changes can
++ only be done by creating a new major version of the extension.
++ </description>
++
++ <interface name="wp_single_pixel_buffer_manager_v1" version="1">
++ <description summary="global factory for single-pixel buffers">
++ The wp_single_pixel_buffer_manager_v1 interface is a factory for
++ single-pixel buffers.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the manager">
++ Destroy the wp_single_pixel_buffer_manager_v1 object.
++
++ The child objects created via this interface are unaffected.
++ </description>
++ </request>
++
++ <request name="create_u32_rgba_buffer">
++ <description summary="create a 1×1 buffer from 32-bit RGBA values">
++ Create a single-pixel buffer from four 32-bit RGBA values.
++
++ Unless specified in another protocol extension, the RGBA values use
++ pre-multiplied alpha.
++
++ The width and height of the buffer are 1.
++ </description>
++ <arg name="id" type="new_id" interface="wl_buffer"/>
++ <arg name="r" type="uint" summary="value of the buffer's red channel"/>
++ <arg name="g" type="uint" summary="value of the buffer's green channel"/>
++ <arg name="b" type="uint" summary="value of the buffer's blue channel"/>
++ <arg name="a" type="uint" summary="value of the buffer's alpha channel"/>
++ </request>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++XDG Activation protocol
++
++Maintainers:
++Aleix Pol Gonzalez <aleixpol@kde.org>
--- /dev/null
--- /dev/null
++Interoperation with X11
++=======================
++
++*This document is non-normative.*
++
++The former
++`X11 Startup notification protocol <https://cgit.freedesktop.org/startup-notification/tree/doc/startup-notification.txt>`_
++defines the use of the ``DESKTOP_STARTUP_ID`` environment variable to propagate
++startup sequences ("activation tokens" in this protocol) between launcher and
++launchee.
++
++These startup sequence IDs are defined as a globally unique string with a
++``[unique]_TIME[timestamp]`` format, where the ID as a whole is used for startup
++notification and the timestamp is used for focus requests and focus stealing
++prevention.
++
++In order to observe mixed usage scenarios where Wayland and X11 clients might
++be launching each other, it is possible for a compositor to manage a shared
++pool of activation tokens.
++
++Scenario 1. Wayland client spawns X11 client
++--------------------------------------------
++
++1. Wayland client requests token.
++2. Wayland client spawns X11 client, sets ``$DESKTOP_STARTUP_ID`` in its
++ environment with the token string.
++3. X11 client starts.
++4. X11 client sends startup-notification ``remove`` message with the activation
++ ``$DESKTOP_STARTUP_ID`` content.
++5. Compositor receives startup notification message, matches ID with
++ the common pool.
++6. The startup feedback is finished.
++7. X11 client requests focus.
++8. Compositor applies internal policies to allow/deny focus switch.
++
++Scenario 2. X11 client spawns Wayland client
++--------------------------------------------
++
++1. X11 client builds a "globally unique" ID
++2. X11 client sends startup-notification ``new`` message with the ID.
++3. Compositor receives startup notification message, adds the ID to
++ the common pool.
++4. X11 client spawns Wayland client, sets ``$DESKTOP_STARTUP_ID`` in its
++ environment.
++5. Wayland client starts.
++6. Wayland client requests surface activation with the activation token,
++ as received from ``$DESKTOP_STARTUP_ID``.
++7. Compositor receives the request, matches ID with the common pool
++8. The startup feedback is finished.
++9. Compositor applies internal policies to allow/deny focus switch.
++
++Caveats
++-------
++
++- For legacy reasons, the usage of ``$DESKTOP_STARTUP_ID`` (even if as a
++ fallback) should be observed in compositors and clients that are
++ concerned with X11 interoperation.
++
++- Depending on the X11 startup-notification implementation in use by the
++ compositor, the usage of the ``_TIME[timestamp]`` suffix may be mandatory
++ for its correct behavior in the first scenario, the startup-notification
++ reference library is one such implementation. Compositors may work
++ this around by adding a matching suffix to the generated activation tokens.
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_activation_v1">
++
++ <copyright>
++ Copyright © 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
++ Copyright © 2020 Carlos Garnacho <carlosg@gnome.org>
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <description summary="Protocol for requesting activation of surfaces">
++ The way for a client to pass focus to another toplevel is as follows.
++
++ The client that intends to activate another toplevel uses the
++ xdg_activation_v1.get_activation_token request to get an activation token.
++ This token is then forwarded to the client, which is supposed to activate
++ one of its surfaces, through a separate band of communication.
++
++ One established way of doing this is through the XDG_ACTIVATION_TOKEN
++ environment variable of a newly launched child process. The child process
++ should unset the environment variable again right after reading it out in
++ order to avoid propagating it to other child processes.
++
++ Another established way exists for Applications implementing the D-Bus
++ interface org.freedesktop.Application, which should get their token under
++ XDG_ACTIVATION_TOKEN on their platform_data.
++
++ In general activation tokens may be transferred across clients through
++ means not described in this protocol.
++
++ The client to be activated will then pass the token
++ it received to the xdg_activation_v1.activate request. The compositor can
++ then use this token to decide how to react to the activation request.
++
++ The token the activating client gets may be ineffective either already at
++ the time it receives it, for example if it was not focused, for focus
++ stealing prevention. The activating client will have no way to discover
++ the validity of the token, and may still forward it to the to be activated
++ client.
++
++ The created activation token may optionally get information attached to it
++ that can be used by the compositor to identify the application that we
++ intend to activate. This can for example be used to display a visual hint
++ about what application is being started.
++
++ Warning! The protocol described in this file is currently in the testing
++ phase. Backward compatible changes may be added together with the
++ corresponding interface version bump. Backward incompatible changes can
++ only be done by creating a new major version of the extension.
++ </description>
++
++ <interface name="xdg_activation_v1" version="1">
++ <description summary="interface for activating surfaces">
++ A global interface used for informing the compositor about applications
++ being activated or started, or for applications to request to be
++ activated.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_activation object">
++ Notify the compositor that the xdg_activation object will no longer be
++ used.
++
++ The child objects created via this interface are unaffected and should
++ be destroyed separately.
++ </description>
++ </request>
++
++ <request name="get_activation_token">
++ <description summary="requests a token">
++ Creates an xdg_activation_token_v1 object that will provide
++ the initiating client with a unique token for this activation. This
++ token should be offered to the clients to be activated.
++ </description>
++
++ <arg name="id" type="new_id" interface="xdg_activation_token_v1"/>
++ </request>
++
++ <request name="activate">
++ <description summary="notify new interaction being available">
++ Requests surface activation. It's up to the compositor to display
++ this information as desired, for example by placing the surface above
++ the rest.
++
++ The compositor may know who requested this by checking the activation
++ token and might decide not to follow through with the activation if it's
++ considered unwanted.
++
++ Compositors can ignore unknown activation tokens when an invalid
++ token is passed.
++ </description>
++ <arg name="token" type="string" summary="the activation token of the initiating client"/>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="the wl_surface to activate"/>
++ </request>
++ </interface>
++
++ <interface name="xdg_activation_token_v1" version="1">
++ <description summary="an exported activation handle">
++ An object for setting up a token and receiving a token handle that can
++ be passed as an activation token to another client.
++
++ The object is created using the xdg_activation_v1.get_activation_token
++ request. This object should then be populated with the app_id, surface
++ and serial information and committed. The compositor shall then issue a
++ done event with the token. In case the request's parameters are invalid,
++ the compositor will provide an invalid token.
++ </description>
++
++ <enum name="error">
++ <entry name="already_used" value="0"
++ summary="The token has already been used previously"/>
++ </enum>
++
++ <request name="set_serial">
++ <description summary="specifies the seat and serial of the activating event">
++ Provides information about the seat and serial event that requested the
++ token.
++
++ The serial can come from an input or focus event. For instance, if a
++ click triggers the launch of a third-party client, the launcher client
++ should send a set_serial request with the serial and seat from the
++ wl_pointer.button event.
++
++ Some compositors might refuse to activate toplevels when the token
++ doesn't have a valid and recent enough event serial.
++
++ Must be sent before commit. This information is optional.
++ </description>
++ <arg name="serial" type="uint"
++ summary="the serial of the event that triggered the activation"/>
++ <arg name="seat" type="object" interface="wl_seat"
++ summary="the wl_seat of the event"/>
++ </request>
++
++ <request name="set_app_id">
++ <description summary="specifies the application being activated">
++ The requesting client can specify an app_id to associate the token
++ being created with it.
++
++ Must be sent before commit. This information is optional.
++ </description>
++ <arg name="app_id" type="string"
++ summary="the application id of the client being activated."/>
++ </request>
++
++ <request name="set_surface">
++ <description summary="specifies the surface requesting activation">
++ This request sets the surface requesting the activation. Note, this is
++ different from the surface that will be activated.
++
++ Some compositors might refuse to activate toplevels when the token
++ doesn't have a requesting surface.
++
++ Must be sent before commit. This information is optional.
++ </description>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="the requesting surface"/>
++ </request>
++
++ <request name="commit">
++ <description summary="issues the token request">
++ Requests an activation token based on the different parameters that
++ have been offered through set_serial, set_surface and set_app_id.
++ </description>
++ </request>
++
++ <event name="done">
++ <description summary="the exported activation token">
++ The 'done' event contains the unique token of this activation request
++ and notifies that the provider is done.
++ </description>
++ <arg name="token" type="string" summary="the exported activation token"/>
++ </event>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_activation_token_v1 object">
++ Notify the compositor that the xdg_activation_token_v1 object will no
++ longer be used.
++ </description>
++ </request>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++#include "@PROTOCOL_CLIENT_INCLUDE_FILE@"
++#include "@PROTOCOL_SERVER_INCLUDE_FILE@"
++
++/* This is a build-test only */
++
++using namespace std;
++
++int
++main(int argc, char **argv)
++{
++ (void)argc;
++ (void)argv;
++ return 0;
++}
--- /dev/null
--- /dev/null
++#include "@PROTOCOL_CLIENT_INCLUDE_FILE@"
++#include "@PROTOCOL_SERVER_INCLUDE_FILE@"
++
++/* This is a build-test only */
++
++int
++main(int argc, char **argv)
++{
++ (void)argc;
++ (void)argv;
++ return 0;
++}
--- /dev/null
--- /dev/null
++prog_scan_sh = find_program('scan.sh')
++dep_scanner = dependency('wayland-scanner', version: '>=1.20.0', native: true)
++prog_scanner = find_program(dep_scanner.get_variable(pkgconfig: 'wayland_scanner'))
++
++libwayland = [
++ dependency('wayland-client'),
++ dependency('wayland-server'),
++]
++
++# Check that each protocol passes through the scanner
++foreach protocol_file : protocol_files
++ protocol_path = join_paths(wayland_protocols_srcdir, protocol_file)
++ test_name = 'scan-@0@'.format(protocol_file.underscorify())
++ test(test_name, prog_scan_sh,
++ args: protocol_path,
++ env: [
++ 'SCANNER=@0@'.format(prog_scanner.full_path()),
++ ]
++ )
++endforeach
++
++# Check buildability
++
++add_languages('c', 'cpp', native: false)
++replace = find_program('replace.py')
++
++extra_linker_flags = meson.get_compiler('c').get_supported_link_arguments([
++ '-Wl,--unresolved-symbols=ignore-all',
++])
++
++foreach protocol_file : protocol_files
++ xml_file = fs.name(protocol_file)
++ xml_components = xml_file.split('.')
++ protocol_base_file_name = xml_components[0]
++
++ protocol_path = files(join_paths(wayland_protocols_srcdir, protocol_file))
++ client_header_path = '@0@-client.h'.format(protocol_base_file_name)
++ server_header_path = '@0@-server.h'.format(protocol_base_file_name)
++ code_path = '@0@-code.c'.format(protocol_base_file_name)
++ client_header = custom_target(
++ client_header_path,
++ output: client_header_path,
++ input: protocol_path,
++ command: [
++ prog_scanner,
++ '--strict',
++ 'client-header',
++ '@INPUT@',
++ '@OUTPUT@',
++ ],
++ install: false,
++ )
++ server_header = custom_target(
++ server_header_path,
++ output: server_header_path,
++ input: protocol_path,
++ command: [
++ prog_scanner,
++ '--strict',
++ 'server-header',
++ '@INPUT@',
++ '@OUTPUT@',
++ ],
++ install: false,
++ )
++ code = custom_target(
++ code_path,
++ output: code_path,
++ input: protocol_path,
++ command: [
++ prog_scanner,
++ '--strict',
++ 'private-code',
++ '@INPUT@',
++ '@OUTPUT@',
++ ],
++ install: false,
++ )
++
++ replace_command = [
++ replace,
++ '@INPUT@',
++ '@OUTPUT@',
++ 'PROTOCOL_CLIENT_INCLUDE_FILE',
++ client_header.full_path(),
++ 'PROTOCOL_SERVER_INCLUDE_FILE',
++ server_header.full_path(),
++ ]
++
++ # Check that header can be included by a pedantic C99 compiler
++ test_name = 'test-build-pedantic-@0@'.format(protocol_file.underscorify())
++ test_name_source = '@0@.c'.format(test_name)
++ test_source = custom_target(
++ test_name_source,
++ input: 'build-pedantic.c.in',
++ output: test_name_source,
++ command: replace_command,
++ )
++ pedantic_test_executable = executable(
++ test_name,
++ [
++ test_source,
++ client_header,
++ server_header,
++ code
++ ],
++ link_args: extra_linker_flags,
++ dependencies: libwayland,
++ c_args: [
++ '-std=c99',
++ '-pedantic',
++ '-Wall',
++ '-Werror' ],
++ install: false,
++ )
++ test(test_name, pedantic_test_executable)
++
++ # Check that the header
++ if not protocol_file.contains('xdg-foreign-unstable-v1')
++ test_name = 'test-build-cxx-@0@'.format(protocol_file.underscorify())
++ test_name_source = '@0@.cc'.format(test_name)
++ test_source = custom_target(
++ test_name_source,
++ input: 'build-cxx.cc.in',
++ output: test_name_source,
++ command: replace_command,
++ )
++ cxx_test_executable = executable(
++ test_name,
++ [
++ test_source,
++ client_header,
++ server_header,
++ ],
++ link_args: extra_linker_flags,
++ dependencies: libwayland,
++ cpp_args: [
++ '-Wall',
++ '-Werror',
++ ],
++ install: false,
++ )
++ test(test_name, cxx_test_executable)
++ endif
++endforeach
--- /dev/null
--- /dev/null
++#!/usr/bin/env python3
++
++import sys
++
++execpath, inpath, outpath, *dict_list = sys.argv
++
++dictonary = {}
++while dict_list:
++ key, value, *rest = dict_list
++ dictonary[key] = value
++ dict_list = rest
++
++infile = open(inpath, 'r')
++outfile = open(outpath, 'w')
++
++buf = infile.read()
++infile.close()
++
++for key, value in dictonary.items():
++ buf = buf.replace('@{}@'.format(key), value)
++
++outfile.write(buf)
++outfile.close()
--- /dev/null
--- /dev/null
++#!/bin/sh -e
++
++if [ "x$SCANNER" = "x" ] ; then
++ echo "No scanner present, test skipped." 1>&2
++ exit 77
++fi
++
++$SCANNER client-header --strict $1 /dev/null
++$SCANNER server-header --strict $1 /dev/null
++$SCANNER private-code --strict $1 /dev/null
++$SCANNER public-code --strict $1 /dev/null
--- /dev/null
--- /dev/null
++Fullscreen shell protocol
++
++Maintainers:
++Jason Ekstrand <jason@jlekstrand.net>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="fullscreen_shell_unstable_v1">
++
++ <copyright>
++ Copyright © 2016 Yong Bakos
++ Copyright © 2015 Jason Ekstrand
++ Copyright © 2015 Jonas Ådahl
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="zwp_fullscreen_shell_v1" version="1">
++ <description summary="displays a single surface per output">
++ Displays a single surface per output.
++
++ This interface provides a mechanism for a single client to display
++ simple full-screen surfaces. While there technically may be multiple
++ clients bound to this interface, only one of those clients should be
++ shown at a time.
++
++ To present a surface, the client uses either the present_surface or
++ present_surface_for_mode requests. Presenting a surface takes effect
++ on the next wl_surface.commit. See the individual requests for
++ details about scaling and mode switches.
++
++ The client can have at most one surface per output at any time.
++ Requesting a surface to be presented on an output that already has a
++ surface replaces the previously presented surface. Presenting a null
++ surface removes its content and effectively disables the output.
++ Exactly what happens when an output is "disabled" is
++ compositor-specific. The same surface may be presented on multiple
++ outputs simultaneously.
++
++ Once a surface is presented on an output, it stays on that output
++ until either the client removes it or the compositor destroys the
++ output. This way, the client can update the output's contents by
++ simply attaching a new buffer.
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible changes
++ may be added together with the corresponding interface version bump.
++ Backward incompatible changes are done by bumping the version number in
++ the protocol and interface names and resetting the interface version.
++ Once the protocol is to be declared stable, the 'z' prefix and the
++ version number in the protocol and interface names are removed and the
++ interface version number is reset.
++ </description>
++
++ <request name="release" type="destructor">
++ <description summary="release the wl_fullscreen_shell interface">
++ Release the binding from the wl_fullscreen_shell interface.
++
++ This destroys the server-side object and frees this binding. If
++ the client binds to wl_fullscreen_shell multiple times, it may wish
++ to free some of those bindings.
++ </description>
++ </request>
++
++ <enum name="capability">
++ <description summary="capabilities advertised by the compositor">
++ Various capabilities that can be advertised by the compositor. They
++ are advertised one-at-a-time when the wl_fullscreen_shell interface is
++ bound. See the wl_fullscreen_shell.capability event for more details.
++
++ ARBITRARY_MODES:
++ This is a hint to the client that indicates that the compositor is
++ capable of setting practically any mode on its outputs. If this
++ capability is provided, wl_fullscreen_shell.present_surface_for_mode
++ will almost never fail and clients should feel free to set whatever
++ mode they like. If the compositor does not advertise this, it may
++ still support some modes that are not advertised through wl_global.mode
++ but it is less likely.
++
++ CURSOR_PLANE:
++ This is a hint to the client that indicates that the compositor can
++ handle a cursor surface from the client without actually compositing.
++ This may be because of a hardware cursor plane or some other mechanism.
++ If the compositor does not advertise this capability then setting
++ wl_pointer.cursor may degrade performance or be ignored entirely. If
++ CURSOR_PLANE is not advertised, it is recommended that the client draw
++ its own cursor and set wl_pointer.cursor(NULL).
++ </description>
++ <entry name="arbitrary_modes" value="1" summary="compositor is capable of almost any output mode"/>
++ <entry name="cursor_plane" value="2" summary="compositor has a separate cursor plane"/>
++ </enum>
++
++ <event name="capability">
++ <description summary="advertises a capability of the compositor">
++ Advertises a single capability of the compositor.
++
++ When the wl_fullscreen_shell interface is bound, this event is emitted
++ once for each capability advertised. Valid capabilities are given by
++ the wl_fullscreen_shell.capability enum. If clients want to take
++ advantage of any of these capabilities, they should use a
++ wl_display.sync request immediately after binding to ensure that they
++ receive all the capability events.
++ </description>
++ <arg name="capability" type="uint" enum="capability" />
++ </event>
++
++ <enum name="present_method">
++ <description summary="different method to set the surface fullscreen">
++ Hints to indicate to the compositor how to deal with a conflict
++ between the dimensions of the surface and the dimensions of the
++ output. The compositor is free to ignore this parameter.
++ </description>
++ <entry name="default" value="0" summary="no preference, apply default policy"/>
++ <entry name="center" value="1" summary="center the surface on the output"/>
++ <entry name="zoom" value="2" summary="scale the surface, preserving aspect ratio, to the largest size that will fit on the output" />
++ <entry name="zoom_crop" value="3" summary="scale the surface, preserving aspect ratio, to fully fill the output cropping if needed" />
++ <entry name="stretch" value="4" summary="scale the surface to the size of the output ignoring aspect ratio" />
++ </enum>
++
++ <request name="present_surface">
++ <description summary="present surface for display">
++ Present a surface on the given output.
++
++ If the output is null, the compositor will present the surface on
++ whatever display (or displays) it thinks best. In particular, this
++ may replace any or all surfaces currently presented so it should
++ not be used in combination with placing surfaces on specific
++ outputs.
++
++ The method parameter is a hint to the compositor for how the surface
++ is to be presented. In particular, it tells the compositor how to
++ handle a size mismatch between the presented surface and the
++ output. The compositor is free to ignore this parameter.
++
++ The "zoom", "zoom_crop", and "stretch" methods imply a scaling
++ operation on the surface. This will override any kind of output
++ scaling, so the buffer_scale property of the surface is effectively
++ ignored.
++
++ This request gives the surface the role of a fullscreen shell surface.
++ If the surface already has another role, it raises a role protocol
++ error.
++ </description>
++ <arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
++ <arg name="method" type="uint" enum="present_method" />
++ <arg name="output" type="object" interface="wl_output" allow-null="true"/>
++ </request>
++
++ <request name="present_surface_for_mode">
++ <description summary="present surface for display at a particular mode">
++ Presents a surface on the given output for a particular mode.
++
++ If the current size of the output differs from that of the surface,
++ the compositor will attempt to change the size of the output to
++ match the surface. The result of the mode-switch operation will be
++ returned via the provided wl_fullscreen_shell_mode_feedback object.
++
++ If the current output mode matches the one requested or if the
++ compositor successfully switches the mode to match the surface,
++ then the mode_successful event will be sent and the output will
++ contain the contents of the given surface. If the compositor
++ cannot match the output size to the surface size, the mode_failed
++ will be sent and the output will contain the contents of the
++ previously presented surface (if any). If another surface is
++ presented on the given output before either of these has a chance
++ to happen, the present_cancelled event will be sent.
++
++ Due to race conditions and other issues unknown to the client, no
++ mode-switch operation is guaranteed to succeed. However, if the
++ mode is one advertised by wl_output.mode or if the compositor
++ advertises the ARBITRARY_MODES capability, then the client should
++ expect that the mode-switch operation will usually succeed.
++
++ If the size of the presented surface changes, the resulting output
++ is undefined. The compositor may attempt to change the output mode
++ to compensate. However, there is no guarantee that a suitable mode
++ will be found and the client has no way to be notified of success
++ or failure.
++
++ The framerate parameter specifies the desired framerate for the
++ output in mHz. The compositor is free to ignore this parameter. A
++ value of 0 indicates that the client has no preference.
++
++ If the value of wl_output.scale differs from wl_surface.buffer_scale,
++ then the compositor may choose a mode that matches either the buffer
++ size or the surface size. In either case, the surface will fill the
++ output.
++
++ This request gives the surface the role of a fullscreen shell surface.
++ If the surface already has another role, it raises a role protocol
++ error.
++ </description>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ <arg name="output" type="object" interface="wl_output"/>
++ <arg name="framerate" type="int"/>
++ <arg name="feedback" type="new_id" interface="zwp_fullscreen_shell_mode_feedback_v1"/>
++ </request>
++
++ <enum name="error">
++ <description summary="wl_fullscreen_shell error values">
++ These errors can be emitted in response to wl_fullscreen_shell requests.
++ </description>
++ <entry name="invalid_method" value="0" summary="present_method is not known"/>
++ <entry name="role" value="1" summary="given wl_surface has another role"/>
++ </enum>
++ </interface>
++
++ <interface name="zwp_fullscreen_shell_mode_feedback_v1" version="1">
++ <event name="mode_successful" type="destructor">
++ <description summary="mode switch succeeded">
++ This event indicates that the attempted mode switch operation was
++ successful. A surface of the size requested in the mode switch
++ will fill the output without scaling.
++
++ Upon receiving this event, the client should destroy the
++ wl_fullscreen_shell_mode_feedback object.
++ </description>
++ </event>
++
++ <event name="mode_failed" type="destructor">
++ <description summary="mode switch failed">
++ This event indicates that the attempted mode switch operation
++ failed. This may be because the requested output mode is not
++ possible or it may mean that the compositor does not want to allow it.
++
++ Upon receiving this event, the client should destroy the
++ wl_fullscreen_shell_mode_feedback object.
++ </description>
++ </event>
++
++ <event name="present_cancelled" type="destructor">
++ <description summary="mode switch cancelled">
++ This event indicates that the attempted mode switch operation was
++ cancelled. Most likely this is because the client requested a
++ second mode switch before the first one completed.
++
++ Upon receiving this event, the client should destroy the
++ wl_fullscreen_shell_mode_feedback object.
++ </description>
++ </event>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++Screensaver inhibition protocol
++
++Maintainers:
++Bryce Harrington <bryce@osg.samsung.com>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="idle_inhibit_unstable_v1">
++
++ <copyright>
++ Copyright © 2015 Samsung Electronics Co., Ltd
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="zwp_idle_inhibit_manager_v1" version="1">
++ <description summary="control behavior when display idles">
++ This interface permits inhibiting the idle behavior such as screen
++ blanking, locking, and screensaving. The client binds the idle manager
++ globally, then creates idle-inhibitor objects for each surface.
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible changes
++ may be added together with the corresponding interface version bump.
++ Backward incompatible changes are done by bumping the version number in
++ the protocol and interface names and resetting the interface version.
++ Once the protocol is to be declared stable, the 'z' prefix and the
++ version number in the protocol and interface names are removed and the
++ interface version number is reset.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the idle inhibitor object">
++ Destroy the inhibit manager.
++ </description>
++ </request>
++
++ <request name="create_inhibitor">
++ <description summary="create a new inhibitor object">
++ Create a new inhibitor object associated with the given surface.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_idle_inhibitor_v1"/>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="the surface that inhibits the idle behavior"/>
++ </request>
++
++ </interface>
++
++ <interface name="zwp_idle_inhibitor_v1" version="1">
++ <description summary="context object for inhibiting idle behavior">
++ An idle inhibitor prevents the output that the associated surface is
++ visible on from being set to a state where it is not visually usable due
++ to lack of user interaction (e.g. blanked, dimmed, locked, set to power
++ save, etc.) Any screensaver processes are also blocked from displaying.
++
++ If the surface is destroyed, unmapped, becomes occluded, loses
++ visibility, or otherwise becomes not visually relevant for the user, the
++ idle inhibitor will not be honored by the compositor; if the surface
++ subsequently regains visibility the inhibitor takes effect once again.
++ Likewise, the inhibitor isn't honored if the system was already idled at
++ the time the inhibitor was established, although if the system later
++ de-idles and re-idles the inhibitor will take effect.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the idle inhibitor object">
++ Remove the inhibitor effect from the associated wl_surface.
++ </description>
++ </request>
++
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++Input method protocol
++
++Maintainers:
++Jan Arne Petersen <janarne@gmail.com>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="input_method_unstable_v1">
++
++ <copyright>
++ Copyright © 2012, 2013 Intel Corporation
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="zwp_input_method_context_v1" version="1">
++ <description summary="input method context">
++ Corresponds to a text input on the input method side. An input method context
++ is created on text input activation on the input method side. It allows
++ receiving information about the text input from the application via events.
++ Input method contexts do not keep state after deactivation and should be
++ destroyed after deactivation is handled.
++
++ Text is generally UTF-8 encoded, indices and lengths are in bytes.
++
++ Serials are used to synchronize the state between the text input and
++ an input method. New serials are sent by the text input in the
++ commit_state request and are used by the input method to indicate
++ the known text input state in events like preedit_string, commit_string,
++ and keysym. The text input can then ignore events from the input method
++ which are based on an outdated state (for example after a reset).
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible changes
++ may be added together with the corresponding interface version bump.
++ Backward incompatible changes are done by bumping the version number in
++ the protocol and interface names and resetting the interface version.
++ Once the protocol is to be declared stable, the 'z' prefix and the
++ version number in the protocol and interface names are removed and the
++ interface version number is reset.
++ </description>
++
++ <request name="destroy" type="destructor"/>
++
++ <request name="commit_string">
++ <description summary="commit string">
++ Send the commit string text for insertion to the application.
++
++ The text to commit could be either just a single character after a key
++ press or the result of some composing (pre-edit). It could be also an
++ empty text when some text should be removed (see
++ delete_surrounding_text) or when the input cursor should be moved (see
++ cursor_position).
++
++ Any previously set composing text will be removed.
++ </description>
++ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++ <arg name="text" type="string"/>
++ </request>
++
++ <request name="preedit_string">
++ <description summary="pre-edit string">
++ Send the pre-edit string text to the application text input.
++
++ The commit text can be used to replace the pre-edit text on reset (for
++ example on unfocus).
++
++ Previously sent preedit_style and preedit_cursor requests are also
++ processed by the text_input.
++ </description>
++ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++ <arg name="text" type="string"/>
++ <arg name="commit" type="string"/>
++ </request>
++
++ <request name="preedit_styling">
++ <description summary="pre-edit styling">
++ Set the styling information on composing text. The style is applied for
++ length in bytes from index relative to the beginning of
++ the composing text (as byte offset). Multiple styles can
++ be applied to a composing text.
++
++ This request should be sent before sending a preedit_string request.
++ </description>
++ <arg name="index" type="uint"/>
++ <arg name="length" type="uint"/>
++ <arg name="style" type="uint"/>
++ </request>
++
++ <request name="preedit_cursor">
++ <description summary="pre-edit cursor">
++ Set the cursor position inside the composing text (as byte offset)
++ relative to the start of the composing text.
++
++ When index is negative no cursor should be displayed.
++
++ This request should be sent before sending a preedit_string request.
++ </description>
++ <arg name="index" type="int"/>
++ </request>
++
++ <request name="delete_surrounding_text">
++ <description summary="delete text">
++ Remove the surrounding text.
++
++ This request will be handled on the text_input side directly following
++ a commit_string request.
++ </description>
++ <arg name="index" type="int"/>
++ <arg name="length" type="uint"/>
++ </request>
++
++ <request name="cursor_position">
++ <description summary="set cursor to a new position">
++ Set the cursor and anchor to a new position. Index is the new cursor
++ position in bytes (when >= 0 this is relative to the end of the inserted text,
++ otherwise it is relative to the beginning of the inserted text). Anchor is
++ the new anchor position in bytes (when >= 0 this is relative to the end of the
++ inserted text, otherwise it is relative to the beginning of the inserted
++ text). When there should be no selected text, anchor should be the same
++ as index.
++
++ This request will be handled on the text_input side directly following
++ a commit_string request.
++ </description>
++ <arg name="index" type="int"/>
++ <arg name="anchor" type="int"/>
++ </request>
++
++ <request name="modifiers_map">
++ <arg name="map" type="array"/>
++ </request>
++
++ <request name="keysym">
++ <description summary="keysym">
++ Notify when a key event was sent. Key events should not be used for
++ normal text input operations, which should be done with commit_string,
++ delete_surrounding_text, etc. The key event follows the wl_keyboard key
++ event convention. Sym is an XKB keysym, state is a wl_keyboard key_state.
++ </description>
++ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++ <arg name="time" type="uint"/>
++ <arg name="sym" type="uint"/>
++ <arg name="state" type="uint"/>
++ <arg name="modifiers" type="uint"/>
++ </request>
++
++ <request name="grab_keyboard">
++ <description summary="grab hardware keyboard">
++ Allow an input method to receive hardware keyboard input and process
++ key events to generate text events (with pre-edit) over the wire. This
++ allows input methods which compose multiple key events for inputting
++ text like it is done for CJK languages.
++ </description>
++ <arg name="keyboard" type="new_id" interface="wl_keyboard"/>
++ </request>
++
++ <request name="key">
++ <description summary="forward key event">
++ Forward a wl_keyboard::key event to the client that was not processed
++ by the input method itself. Should be used when filtering key events
++ with grab_keyboard. The arguments should be the ones from the
++ wl_keyboard::key event.
++
++ For generating custom key events use the keysym request instead.
++ </description>
++ <arg name="serial" type="uint" summary="serial from wl_keyboard::key"/>
++ <arg name="time" type="uint" summary="time from wl_keyboard::key"/>
++ <arg name="key" type="uint" summary="key from wl_keyboard::key"/>
++ <arg name="state" type="uint" summary="state from wl_keyboard::key"/>
++ </request>
++
++ <request name="modifiers">
++ <description summary="forward modifiers event">
++ Forward a wl_keyboard::modifiers event to the client that was not
++ processed by the input method itself. Should be used when filtering
++ key events with grab_keyboard. The arguments should be the ones
++ from the wl_keyboard::modifiers event.
++ </description>
++ <arg name="serial" type="uint" summary="serial from wl_keyboard::modifiers"/>
++ <arg name="mods_depressed" type="uint" summary="mods_depressed from wl_keyboard::modifiers"/>
++ <arg name="mods_latched" type="uint" summary="mods_latched from wl_keyboard::modifiers"/>
++ <arg name="mods_locked" type="uint" summary="mods_locked from wl_keyboard::modifiers"/>
++ <arg name="group" type="uint" summary="group from wl_keyboard::modifiers"/>
++ </request>
++
++ <request name="language">
++ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++ <arg name="language" type="string"/>
++ </request>
++
++ <request name="text_direction">
++ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++ <arg name="direction" type="uint"/>
++ </request>
++
++ <event name="surrounding_text">
++ <description summary="surrounding text event">
++ The plain surrounding text around the input position. Cursor is the
++ position in bytes within the surrounding text relative to the beginning
++ of the text. Anchor is the position in bytes of the selection anchor
++ within the surrounding text relative to the beginning of the text. If
++ there is no selected text then anchor is the same as cursor.
++ </description>
++ <arg name="text" type="string"/>
++ <arg name="cursor" type="uint"/>
++ <arg name="anchor" type="uint"/>
++ </event>
++
++ <event name="reset">
++ </event>
++
++ <event name="content_type">
++ <arg name="hint" type="uint"/>
++ <arg name="purpose" type="uint"/>
++ </event>
++
++ <event name="invoke_action">
++ <arg name="button" type="uint"/>
++ <arg name="index" type="uint"/>
++ </event>
++
++ <event name="commit_state">
++ <arg name="serial" type="uint" summary="serial of text input state"/>
++ </event>
++
++ <event name="preferred_language">
++ <arg name="language" type="string"/>
++ </event>
++ </interface>
++
++ <interface name="zwp_input_method_v1" version="1">
++ <description summary="input method">
++ An input method object is responsible for composing text in response to
++ input from hardware or virtual keyboards. There is one input method
++ object per seat. On activate there is a new input method context object
++ created which allows the input method to communicate with the text input.
++ </description>
++
++ <event name="activate">
++ <description summary="activate event">
++ A text input was activated. Creates an input method context object
++ which allows communication with the text input.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_input_method_context_v1"/>
++ </event>
++
++ <event name="deactivate">
++ <description summary="deactivate event">
++ The text input corresponding to the context argument was deactivated.
++ The input method context should be destroyed after deactivation is
++ handled.
++ </description>
++ <arg name="context" type="object" interface="zwp_input_method_context_v1"/>
++ </event>
++ </interface>
++
++ <interface name="zwp_input_panel_v1" version="1">
++ <description summary="interface for implementing keyboards">
++ Only one client can bind this interface at a time.
++ </description>
++
++ <request name="get_input_panel_surface">
++ <arg name="id" type="new_id" interface="zwp_input_panel_surface_v1"/>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ </request>
++ </interface>
++
++ <interface name="zwp_input_panel_surface_v1" version="1">
++ <enum name="position">
++ <entry name="center_bottom" value="0"/>
++ </enum>
++
++ <request name="set_toplevel">
++ <description summary="set the surface type as a keyboard">
++ Set the input_panel_surface type to keyboard.
++
++ A keyboard surface is only shown when a text input is active.
++ </description>
++ <arg name="output" type="object" interface="wl_output"/>
++ <arg name="position" type="uint"/>
++ </request>
++
++ <request name="set_overlay_panel">
++ <description summary="set the surface type as an overlay panel">
++ Set the input_panel_surface to be an overlay panel.
++
++ This is shown near the input cursor above the application window when
++ a text input is active.
++ </description>
++ </request>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++High-resolution timestamps for input events.
++
++Maintainers:
++Alexandros Frantzis <alexandros.frantzis@collabora.com>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="input_timestamps_unstable_v1">
++
++ <copyright>
++ Copyright © 2017 Collabora, Ltd.
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <description summary="High-resolution timestamps for input events">
++ This protocol specifies a way for a client to request and receive
++ high-resolution timestamps for input events.
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible changes
++ may be added together with the corresponding interface version bump.
++ Backward incompatible changes are done by bumping the version number in
++ the protocol and interface names and resetting the interface version.
++ Once the protocol is to be declared stable, the 'z' prefix and the
++ version number in the protocol and interface names are removed and the
++ interface version number is reset.
++ </description>
++
++ <interface name="zwp_input_timestamps_manager_v1" version="1">
++ <description summary="context object for high-resolution input timestamps">
++ A global interface used for requesting high-resolution timestamps
++ for input events.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the input timestamps manager object">
++ Informs the server that the client will no longer be using this
++ protocol object. Existing objects created by this object are not
++ affected.
++ </description>
++ </request>
++
++ <request name="get_keyboard_timestamps">
++ <description summary="subscribe to high-resolution keyboard timestamp events">
++ Creates a new input timestamps object that represents a subscription
++ to high-resolution timestamp events for all wl_keyboard events that
++ carry a timestamp.
++
++ If the associated wl_keyboard object is invalidated, either through
++ client action (e.g. release) or server-side changes, the input
++ timestamps object becomes inert and the client should destroy it
++ by calling zwp_input_timestamps_v1.destroy.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_input_timestamps_v1"/>
++ <arg name="keyboard" type="object" interface="wl_keyboard"
++ summary="the wl_keyboard object for which to get timestamp events"/>
++ </request>
++
++ <request name="get_pointer_timestamps">
++ <description summary="subscribe to high-resolution pointer timestamp events">
++ Creates a new input timestamps object that represents a subscription
++ to high-resolution timestamp events for all wl_pointer events that
++ carry a timestamp.
++
++ If the associated wl_pointer object is invalidated, either through
++ client action (e.g. release) or server-side changes, the input
++ timestamps object becomes inert and the client should destroy it
++ by calling zwp_input_timestamps_v1.destroy.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_input_timestamps_v1"/>
++ <arg name="pointer" type="object" interface="wl_pointer"
++ summary="the wl_pointer object for which to get timestamp events"/>
++ </request>
++
++ <request name="get_touch_timestamps">
++ <description summary="subscribe to high-resolution touch timestamp events">
++ Creates a new input timestamps object that represents a subscription
++ to high-resolution timestamp events for all wl_touch events that
++ carry a timestamp.
++
++ If the associated wl_touch object becomes invalid, either through
++ client action (e.g. release) or server-side changes, the input
++ timestamps object becomes inert and the client should destroy it
++ by calling zwp_input_timestamps_v1.destroy.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_input_timestamps_v1"/>
++ <arg name="touch" type="object" interface="wl_touch"
++ summary="the wl_touch object for which to get timestamp events"/>
++ </request>
++ </interface>
++
++ <interface name="zwp_input_timestamps_v1" version="1">
++ <description summary="context object for input timestamps">
++ Provides high-resolution timestamp events for a set of subscribed input
++ events. The set of subscribed input events is determined by the
++ zwp_input_timestamps_manager_v1 request used to create this object.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the input timestamps object">
++ Informs the server that the client will no longer be using this
++ protocol object. After the server processes the request, no more
++ timestamp events will be emitted.
++ </description>
++ </request>
++
++ <event name="timestamp">
++ <description summary="high-resolution timestamp event">
++ The timestamp event is associated with the first subsequent input event
++ carrying a timestamp which belongs to the set of input events this
++ object is subscribed to.
++
++ The timestamp provided by this event is a high-resolution version of
++ the timestamp argument of the associated input event. The provided
++ timestamp is in the same clock domain and is at least as accurate as
++ the associated input event timestamp.
++
++ The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples,
++ each component being an unsigned 32-bit value. Whole seconds are in
++ tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo,
++ and the additional fractional part in tv_nsec as nanoseconds. Hence,
++ for valid timestamps tv_nsec must be in [0, 999999999].
++ </description>
++ <arg name="tv_sec_hi" type="uint"
++ summary="high 32 bits of the seconds part of the timestamp"/>
++ <arg name="tv_sec_lo" type="uint"
++ summary="low 32 bits of the seconds part of the timestamp"/>
++ <arg name="tv_nsec" type="uint"
++ summary="nanoseconds part of the timestamp"/>
++ </event>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++Compositor shortcuts inhibit protocol
++
++Maintainers:
++Olivier Fourdan <ofourdan@redhat.com>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="keyboard_shortcuts_inhibit_unstable_v1">
++
++ <copyright>
++ Copyright © 2017 Red Hat Inc.
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <description summary="Protocol for inhibiting the compositor keyboard shortcuts">
++ This protocol specifies a way for a client to request the compositor
++ to ignore its own keyboard shortcuts for a given seat, so that all
++ key events from that seat get forwarded to a surface.
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible
++ changes may be added together with the corresponding interface
++ version bump.
++ Backward incompatible changes are done by bumping the version
++ number in the protocol and interface names and resetting the
++ interface version. Once the protocol is to be declared stable,
++ the 'z' prefix and the version number in the protocol and
++ interface names are removed and the interface version number is
++ reset.
++ </description>
++
++ <interface name="zwp_keyboard_shortcuts_inhibit_manager_v1" version="1">
++ <description summary="context object for keyboard grab_manager">
++ A global interface used for inhibiting the compositor keyboard shortcuts.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the keyboard shortcuts inhibitor object">
++ Destroy the keyboard shortcuts inhibitor manager.
++ </description>
++ </request>
++
++ <request name="inhibit_shortcuts">
++ <description summary="create a new keyboard shortcuts inhibitor object">
++ Create a new keyboard shortcuts inhibitor object associated with
++ the given surface for the given seat.
++
++ If shortcuts are already inhibited for the specified seat and surface,
++ a protocol error "already_inhibited" is raised by the compositor.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_keyboard_shortcuts_inhibitor_v1"/>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="the surface that inhibits the keyboard shortcuts behavior"/>
++ <arg name="seat" type="object" interface="wl_seat"
++ summary="the wl_seat for which keyboard shortcuts should be disabled"/>
++ </request>
++
++ <enum name="error">
++ <entry name="already_inhibited"
++ value="0"
++ summary="the shortcuts are already inhibited for this surface"/>
++ </enum>
++ </interface>
++
++ <interface name="zwp_keyboard_shortcuts_inhibitor_v1" version="1">
++ <description summary="context object for keyboard shortcuts inhibitor">
++ A keyboard shortcuts inhibitor instructs the compositor to ignore
++ its own keyboard shortcuts when the associated surface has keyboard
++ focus. As a result, when the surface has keyboard focus on the given
++ seat, it will receive all key events originating from the specified
++ seat, even those which would normally be caught by the compositor for
++ its own shortcuts.
++
++ The Wayland compositor is however under no obligation to disable
++ all of its shortcuts, and may keep some special key combo for its own
++ use, including but not limited to one allowing the user to forcibly
++ restore normal keyboard events routing in the case of an unwilling
++ client. The compositor may also use the same key combo to reactivate
++ an existing shortcut inhibitor that was previously deactivated on
++ user request.
++
++ When the compositor restores its own keyboard shortcuts, an
++ "inactive" event is emitted to notify the client that the keyboard
++ shortcuts inhibitor is not effectively active for the surface and
++ seat any more, and the client should not expect to receive all
++ keyboard events.
++
++ When the keyboard shortcuts inhibitor is inactive, the client has
++ no way to forcibly reactivate the keyboard shortcuts inhibitor.
++
++ The user can chose to re-enable a previously deactivated keyboard
++ shortcuts inhibitor using any mechanism the compositor may offer,
++ in which case the compositor will send an "active" event to notify
++ the client.
++
++ If the surface is destroyed, unmapped, or loses the seat's keyboard
++ focus, the keyboard shortcuts inhibitor becomes irrelevant and the
++ compositor will restore its own keyboard shortcuts but no "inactive"
++ event is emitted in this case.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the keyboard shortcuts inhibitor object">
++ Remove the keyboard shortcuts inhibitor from the associated wl_surface.
++ </description>
++ </request>
++
++ <event name="active">
++ <description summary="shortcuts are inhibited">
++ This event indicates that the shortcut inhibitor is active.
++
++ The compositor sends this event every time compositor shortcuts
++ are inhibited on behalf of the surface. When active, the client
++ may receive input events normally reserved by the compositor
++ (see zwp_keyboard_shortcuts_inhibitor_v1).
++
++ This occurs typically when the initial request "inhibit_shortcuts"
++ first becomes active or when the user instructs the compositor to
++ re-enable and existing shortcuts inhibitor using any mechanism
++ offered by the compositor.
++ </description>
++ </event>
++
++ <event name="inactive">
++ <description summary="shortcuts are restored">
++ This event indicates that the shortcuts inhibitor is inactive,
++ normal shortcuts processing is restored by the compositor.
++ </description>
++ </event>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++Linux DMA-BUF protocol
++
++Maintainers:
++Pekka Paalanen <pekka.paalanen@collabora.co.uk>
++Daniel Stone <daniels@collabora.com>
--- /dev/null
--- /dev/null
++.. Copyright 2021 Simon Ser
++
++.. contents::
++
++
++linux-dmabuf feedback introduction
++==================================
++
++linux-dmabuf feedback allows compositors and clients to negotiate optimal buffer
++allocation parameters. This document will assume that the compositor is using a
++rendering API such as OpenGL or Vulkan and KMS as the presentation API: even if
++linux-dmabuf feedback isn't restricted to this use-case, it's the most common.
++
++linux-dmabuf feedback introduces the following concepts:
++
++1. A main device. This is the render device that the compositor is using to
++ perform composition. Compositors should always be able to display a buffer
++ submitted by a client, so this device can be used as a fallback in case none
++ of the more optimized code-paths work. Clients should allocate buffers such
++ that they can be imported and textured from the main device.
++
++2. One or more tranches. Each tranche consists of a target device, allocation
++ flags and a set of format/modifier pairs. A tranche can be seen as a set of
++ formats/modifier pairs that are compatible with the target device.
++
++ A tranche can have the ``scanout`` flag. It means that the target device is
++ a KMS device, and that buffers allocated with one of the format/modifier
++ pairs in the tranche are eligible for direct scanout.
++
++ Clients should use the tranches in order to allocate buffers with the most
++ appropriate format/modifier and also to avoid allocating in private device
++ memory when cross-device operations are going to happen.
++
++linux-dmabuf feedback implementation notes
++==========================================
++
++This section contains recommendations for client and compositor implementations.
++
++For clients
++-----------
++
++Clients are expected to either pick a fixed DRM format beforehand, or
++perform the following steps repeatedly until they find a suitable format.
++
++Basic clients may only support static buffer allocation on startup. These
++clients should do the following:
++
++1. Send a ``get_default_feedback`` request to get global feedback.
++2. Select the device indicated by ``main_device`` for allocation.
++3. For each tranche:
++
++ 1. If ``tranche_target_device`` doesn't match the allocation device, ignore
++ the tranche.
++ 2. Accumulate allocation flags from ``tranche_flags``.
++ 3. Accumulate format/modifier pairs received via ``tranche_formats`` in a
++ list.
++ 4. When the ``tranche_done`` event is received, try to allocate the buffer
++ with the accumulated list of modifiers and allocation flags. If that
++ fails, proceed with the next tranche. If that succeeds, stop the loop.
++
++4. Destroy the feedback object.
++
++Tranches are ordered by preference: the more optimized tranches come first. As
++such, clients should use the first tranche that happens to work.
++
++Some clients may have already selected the device they want to use beforehand.
++These clients can ignore the ``main_device`` event, and ignore tranches whose
++``tranche_target_device`` doesn't match the selected device. Such clients need
++to be prepared for the ``wp_linux_buffer_params.create`` request to potentially
++fail.
++
++If the client allocates a buffer without specifying explicit modifiers on a
++device different from the one indicated by ``main_device``, then the client
++must force a linear layout.
++
++Some clients might support re-negotiating the buffer format/modifier on the
++fly. These clients should send a ``get_surface_feedback`` request and keep the
++feedback object alive after the initial allocation. Each time a new set of
++feedback parameters is received (ended by the ``done`` event), they should
++perform the same steps as basic clients described above. They should detect
++when the optimal allocation parameters didn't change (same
++format/modifier/flags) to avoid needlessly re-allocating their buffers.
++
++Some clients might additionally support switching the device used for
++allocations on the fly. Such clients should send a ``get_surface_feedback``
++request. For each tranche, select the device indicated by
++``tranche_target_device`` for allocation. Accumulate allocation flags (received
++via ``tranche_flags``) and format/modifier pairs (received via
++``tranche_formats``) as usual. When the ``tranche_done`` event is received, try
++to allocate the buffer with the accumulated list of modifiers and the
++allocation flags. Try to import the resulting buffer by sending a
++``wp_linux_buffer_params.create`` request (this might fail). Repeat with each
++tranche until an allocation and import succeeds. Each time a new set of
++feedback parameters is received, they should perform these steps again. They
++should detect when the optimal allocation parameters didn't change (same
++device/format/modifier/flags) to avoid needlessly re-allocating their buffers.
++
++For compositors
++---------------
++
++Basic compositors may only support texturing the DMA-BUFs via a rendering API
++such as OpenGL or Vulkan. Such compositors can send a single tranche as a reply
++to both ``get_default_feedback`` and ``get_surface_feedback``. Set the
++``main_device`` to the rendering device. Send the tranche with
++``tranche_target_device`` set to the rendering device and all of the DRM
++format/modifier pairs supported by the rendering API. Do not set the
++``scanout`` flag in the ``tranche_flags`` event.
++
++Some compositors may support direct scan-out for full-screen surfaces. These
++compositors can re-send the feedback parameters when a surface becomes
++full-screen or leaves full-screen mode if the client has used the
++``get_surface_feedback`` request. The non-full-screen feedback parameters are
++the same as basic compositors described above. The full-screen feedback
++parameters have two tranches: one with the format/modifier pairs supported by
++the KMS plane, with the ``scanout`` flag set in the ``tranche_flags`` event and
++with ``tranche_target_device`` set to the KMS scan-out device; the other with
++the rest of the format/modifier pairs (supported for texturing, but not for
++scan-out), without the ``scanout`` flag set in the ``tranche_flags`` event, and
++with the ``tranche_target_device`` set to the rendering device.
++
++Some compositors may support direct scan-out for all surfaces. These
++compositors can send two tranches for surfaces that become candidates for
++direct scan-out, similarly to compositors supporting direct scan-out for
++fullscreen surfaces. When a surface stops being a candidate for direct
++scan-out, compositors should re-send the feedback parameters optimized for
++texturing only. The way candidates for direct scan-out are selected is
++compositor policy, a possible implementation is to select as many surfaces as
++there are available hardware planes, starting from surfaces closer to the eye.
++
++Some compositors may support multiple devices at the same time. If the
++compositor supports rendering with a fixed device and direct scan-out on a
++secondary device, it may send a separate tranche for surfaces displayed on
++the secondary device that are candidates for direct scan-out. The
++``tranche_target_device`` for this tranche will be the secondary device and
++will not match the ``main_device``.
++
++Some compositors may support switching their rendering device at runtime or
++changing their rendering device depending on the surface. When the rendering
++device changes for a surface, such compositors may re-send the feedback
++parameters with a different ``main_device``. However there is a risk that
++clients don't support switching their device at runtime and continue using the
++previous device. For this reason, compositors should always have a fallback
++rendering device that they initially send as ``main_device``, such that these
++clients use said fallback device.
++
++Compositors should not change the ``main_device`` on-the-fly when explicit
++modifiers are not supported, because there's a risk of importing buffers
++with an implicit non-linear modifier as a linear buffer, resulting in
++misinterpreted buffer contents.
++
++Compositors should not send feedback parameters if they don't have a fallback
++path. For instance, compositors shouldn't send a format/modifier supported for
++direct scan-out but not supported by the rendering API for texturing.
++
++Compositors can decide to use multiple tranches to describe the allocation
++parameters optimized for texturing. For example, if there are formats which
++have a fast texturing path and formats which have a slower texturing path, the
++compositor can decide to expose two separate tranches.
++
++Compositors can decide to use intermediate tranches to describe code-paths
++slower than direct scan-out but faster than texturing. For instance, a
++compositor could insert an intermediate tranche if it's possible to use a
++mem2mem device to convert buffers to be able to use scan-out.
++
++``dev_t`` encoding
++==================
++
++The protocol carries ``dev_t`` values on the wire using arrays. A compositor
++written in C can encode the values as follows:
++
++.. code-block:: c
++
++ struct stat drm_node_stat;
++ struct wl_array dev_array = {
++ .size = sizeof(drm_node_stat.st_rdev),
++ .data = &drm_node_stat.st_rdev,
++ };
++
++A client can decode the values as follows:
++
++.. code-block:: c
++
++ dev_t dev;
++ assert(dev_array->size == sizeof(dev));
++ memcpy(&dev, dev_array->data, sizeof(dev));
++
++Because two DRM nodes can refer to the same DRM device while having different
++``dev_t`` values, clients should use ``drmDevicesEqual`` to compare two
++devices.
++
++``format_table`` encoding
++=========================
++
++The ``format_table`` event carries a file descriptor containing a list of
++format + modifier pairs. The list is an array of pairs which can be accessed
++with this C structure definition:
++
++.. code-block:: c
++
++ struct dmabuf_format_modifier {
++ uint32_t format;
++ uint32_t pad; /* unused */
++ uint64_t modifier;
++ };
++
++Integration with other APIs
++===========================
++
++- libdrm: ``drmGetDeviceFromDevId`` returns a ``drmDevice`` from a device ID.
++- EGL: the `EGL_EXT_device_drm_render_node`_ extension may be used to query the
++ DRM device render node used by a given EGL display. When unavailable, the
++ older `EGL_EXT_device_drm`_ extension may be used as a fallback.
++- Vulkan: the `VK_EXT_physical_device_drm`_ extension may be used to query the
++ DRM device used by a given ``VkPhysicalDevice``.
++
++.. _EGL_EXT_device_drm: https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_device_drm.txt
++.. _EGL_EXT_device_drm_render_node: https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_device_drm_render_node.txt
++.. _VK_EXT_physical_device_drm: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_EXT_physical_device_drm.html
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="linux_dmabuf_unstable_v1">
++
++ <copyright>
++ Copyright © 2014, 2015 Collabora, Ltd.
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="zwp_linux_dmabuf_v1" version="4">
++ <description summary="factory for creating dmabuf-based wl_buffers">
++ Following the interfaces from:
++ https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_image_dma_buf_import.txt
++ https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import_modifiers.txt
++ and the Linux DRM sub-system's AddFb2 ioctl.
++
++ This interface offers ways to create generic dmabuf-based wl_buffers.
++
++ Clients can use the get_surface_feedback request to get dmabuf feedback
++ for a particular surface. If the client wants to retrieve feedback not
++ tied to a surface, they can use the get_default_feedback request.
++
++ The following are required from clients:
++
++ - Clients must ensure that either all data in the dma-buf is
++ coherent for all subsequent read access or that coherency is
++ correctly handled by the underlying kernel-side dma-buf
++ implementation.
++
++ - Don't make any more attachments after sending the buffer to the
++ compositor. Making more attachments later increases the risk of
++ the compositor not being able to use (re-import) an existing
++ dmabuf-based wl_buffer.
++
++ The underlying graphics stack must ensure the following:
++
++ - The dmabuf file descriptors relayed to the server will stay valid
++ for the whole lifetime of the wl_buffer. This means the server may
++ at any time use those fds to import the dmabuf into any kernel
++ sub-system that might accept it.
++
++ However, when the underlying graphics stack fails to deliver the
++ promise, because of e.g. a device hot-unplug which raises internal
++ errors, after the wl_buffer has been successfully created the
++ compositor must not raise protocol errors to the client when dmabuf
++ import later fails.
++
++ To create a wl_buffer from one or more dmabufs, a client creates a
++ zwp_linux_dmabuf_params_v1 object with a zwp_linux_dmabuf_v1.create_params
++ request. All planes required by the intended format are added with
++ the 'add' request. Finally, a 'create' or 'create_immed' request is
++ issued, which has the following outcome depending on the import success.
++
++ The 'create' request,
++ - on success, triggers a 'created' event which provides the final
++ wl_buffer to the client.
++ - on failure, triggers a 'failed' event to convey that the server
++ cannot use the dmabufs received from the client.
++
++ For the 'create_immed' request,
++ - on success, the server immediately imports the added dmabufs to
++ create a wl_buffer. No event is sent from the server in this case.
++ - on failure, the server can choose to either:
++ - terminate the client by raising a fatal error.
++ - mark the wl_buffer as failed, and send a 'failed' event to the
++ client. If the client uses a failed wl_buffer as an argument to any
++ request, the behaviour is compositor implementation-defined.
++
++ For all DRM formats and unless specified in another protocol extension,
++ pre-multiplied alpha is used for pixel values.
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible changes
++ may be added together with the corresponding interface version bump.
++ Backward incompatible changes are done by bumping the version number in
++ the protocol and interface names and resetting the interface version.
++ Once the protocol is to be declared stable, the 'z' prefix and the
++ version number in the protocol and interface names are removed and the
++ interface version number is reset.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="unbind the factory">
++ Objects created through this interface, especially wl_buffers, will
++ remain valid.
++ </description>
++ </request>
++
++ <request name="create_params">
++ <description summary="create a temporary object for buffer parameters">
++ This temporary object is used to collect multiple dmabuf handles into
++ a single batch to create a wl_buffer. It can only be used once and
++ should be destroyed after a 'created' or 'failed' event has been
++ received.
++ </description>
++ <arg name="params_id" type="new_id" interface="zwp_linux_buffer_params_v1"
++ summary="the new temporary"/>
++ </request>
++
++ <event name="format">
++ <description summary="supported buffer format">
++ This event advertises one buffer format that the server supports.
++ All the supported formats are advertised once when the client
++ binds to this interface. A roundtrip after binding guarantees
++ that the client has received all supported formats.
++
++ For the definition of the format codes, see the
++ zwp_linux_buffer_params_v1::create request.
++
++ Starting version 4, the format event is deprecated and must not be
++ sent by compositors. Instead, use get_default_feedback or
++ get_surface_feedback.
++ </description>
++ <arg name="format" type="uint" summary="DRM_FORMAT code"/>
++ </event>
++
++ <event name="modifier" since="3">
++ <description summary="supported buffer format modifier">
++ This event advertises the formats that the server supports, along with
++ the modifiers supported for each format. All the supported modifiers
++ for all the supported formats are advertised once when the client
++ binds to this interface. A roundtrip after binding guarantees that
++ the client has received all supported format-modifier pairs.
++
++ For legacy support, DRM_FORMAT_MOD_INVALID (that is, modifier_hi ==
++ 0x00ffffff and modifier_lo == 0xffffffff) is allowed in this event.
++ It indicates that the server can support the format with an implicit
++ modifier. When a plane has DRM_FORMAT_MOD_INVALID as its modifier, it
++ is as if no explicit modifier is specified. The effective modifier
++ will be derived from the dmabuf.
++
++ A compositor that sends valid modifiers and DRM_FORMAT_MOD_INVALID for
++ a given format supports both explicit modifiers and implicit modifiers.
++
++ For the definition of the format and modifier codes, see the
++ zwp_linux_buffer_params_v1::create and zwp_linux_buffer_params_v1::add
++ requests.
++
++ Starting version 4, the modifier event is deprecated and must not be
++ sent by compositors. Instead, use get_default_feedback or
++ get_surface_feedback.
++ </description>
++ <arg name="format" type="uint" summary="DRM_FORMAT code"/>
++ <arg name="modifier_hi" type="uint"
++ summary="high 32 bits of layout modifier"/>
++ <arg name="modifier_lo" type="uint"
++ summary="low 32 bits of layout modifier"/>
++ </event>
++
++ <!-- Version 4 additions -->
++
++ <request name="get_default_feedback" since="4">
++ <description summary="get default feedback">
++ This request creates a new wp_linux_dmabuf_feedback object not bound
++ to a particular surface. This object will deliver feedback about dmabuf
++ parameters to use if the client doesn't support per-surface feedback
++ (see get_surface_feedback).
++ </description>
++ <arg name="id" type="new_id" interface="zwp_linux_dmabuf_feedback_v1"/>
++ </request>
++
++ <request name="get_surface_feedback" since="4">
++ <description summary="get feedback for a surface">
++ This request creates a new wp_linux_dmabuf_feedback object for the
++ specified wl_surface. This object will deliver feedback about dmabuf
++ parameters to use for buffers attached to this surface.
++
++ If the surface is destroyed before the wp_linux_dmabuf_feedback object,
++ the feedback object becomes inert.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_linux_dmabuf_feedback_v1"/>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ </request>
++ </interface>
++
++ <interface name="zwp_linux_buffer_params_v1" version="4">
++ <description summary="parameters for creating a dmabuf-based wl_buffer">
++ This temporary object is a collection of dmabufs and other
++ parameters that together form a single logical buffer. The temporary
++ object may eventually create one wl_buffer unless cancelled by
++ destroying it before requesting 'create'.
++
++ Single-planar formats only require one dmabuf, however
++ multi-planar formats may require more than one dmabuf. For all
++ formats, an 'add' request must be called once per plane (even if the
++ underlying dmabuf fd is identical).
++
++ You must use consecutive plane indices ('plane_idx' argument for 'add')
++ from zero to the number of planes used by the drm_fourcc format code.
++ All planes required by the format must be given exactly once, but can
++ be given in any order. Each plane index can be set only once.
++ </description>
++
++ <enum name="error">
++ <entry name="already_used" value="0"
++ summary="the dmabuf_batch object has already been used to create a wl_buffer"/>
++ <entry name="plane_idx" value="1"
++ summary="plane index out of bounds"/>
++ <entry name="plane_set" value="2"
++ summary="the plane index was already set"/>
++ <entry name="incomplete" value="3"
++ summary="missing or too many planes to create a buffer"/>
++ <entry name="invalid_format" value="4"
++ summary="format not supported"/>
++ <entry name="invalid_dimensions" value="5"
++ summary="invalid width or height"/>
++ <entry name="out_of_bounds" value="6"
++ summary="offset + stride * height goes out of dmabuf bounds"/>
++ <entry name="invalid_wl_buffer" value="7"
++ summary="invalid wl_buffer resulted from importing dmabufs via
++ the create_immed request on given buffer_params"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="delete this object, used or not">
++ Cleans up the temporary data sent to the server for dmabuf-based
++ wl_buffer creation.
++ </description>
++ </request>
++
++ <request name="add">
++ <description summary="add a dmabuf to the temporary set">
++ This request adds one dmabuf to the set in this
++ zwp_linux_buffer_params_v1.
++
++ The 64-bit unsigned value combined from modifier_hi and modifier_lo
++ is the dmabuf layout modifier. DRM AddFB2 ioctl calls this the
++ fb modifier, which is defined in drm_mode.h of Linux UAPI.
++ This is an opaque token. Drivers use this token to express tiling,
++ compression, etc. driver-specific modifications to the base format
++ defined by the DRM fourcc code.
++
++ Starting from version 4, the invalid_format protocol error is sent if
++ the format + modifier pair was not advertised as supported.
++
++ This request raises the PLANE_IDX error if plane_idx is too large.
++ The error PLANE_SET is raised if attempting to set a plane that
++ was already set.
++ </description>
++ <arg name="fd" type="fd" summary="dmabuf fd"/>
++ <arg name="plane_idx" type="uint" summary="plane index"/>
++ <arg name="offset" type="uint" summary="offset in bytes"/>
++ <arg name="stride" type="uint" summary="stride in bytes"/>
++ <arg name="modifier_hi" type="uint"
++ summary="high 32 bits of layout modifier"/>
++ <arg name="modifier_lo" type="uint"
++ summary="low 32 bits of layout modifier"/>
++ </request>
++
++ <enum name="flags" bitfield="true">
++ <entry name="y_invert" value="1" summary="contents are y-inverted"/>
++ <entry name="interlaced" value="2" summary="content is interlaced"/>
++ <entry name="bottom_first" value="4" summary="bottom field first"/>
++ </enum>
++
++ <request name="create">
++ <description summary="create a wl_buffer from the given dmabufs">
++ This asks for creation of a wl_buffer from the added dmabuf
++ buffers. The wl_buffer is not created immediately but returned via
++ the 'created' event if the dmabuf sharing succeeds. The sharing
++ may fail at runtime for reasons a client cannot predict, in
++ which case the 'failed' event is triggered.
++
++ The 'format' argument is a DRM_FORMAT code, as defined by the
++ libdrm's drm_fourcc.h. The Linux kernel's DRM sub-system is the
++ authoritative source on how the format codes should work.
++
++ The 'flags' is a bitfield of the flags defined in enum "flags".
++ 'y_invert' means the that the image needs to be y-flipped.
++
++ Flag 'interlaced' means that the frame in the buffer is not
++ progressive as usual, but interlaced. An interlaced buffer as
++ supported here must always contain both top and bottom fields.
++ The top field always begins on the first pixel row. The temporal
++ ordering between the two fields is top field first, unless
++ 'bottom_first' is specified. It is undefined whether 'bottom_first'
++ is ignored if 'interlaced' is not set.
++
++ This protocol does not convey any information about field rate,
++ duration, or timing, other than the relative ordering between the
++ two fields in one buffer. A compositor may have to estimate the
++ intended field rate from the incoming buffer rate. It is undefined
++ whether the time of receiving wl_surface.commit with a new buffer
++ attached, applying the wl_surface state, wl_surface.frame callback
++ trigger, presentation, or any other point in the compositor cycle
++ is used to measure the frame or field times. There is no support
++ for detecting missed or late frames/fields/buffers either, and
++ there is no support whatsoever for cooperating with interlaced
++ compositor output.
++
++ The composited image quality resulting from the use of interlaced
++ buffers is explicitly undefined. A compositor may use elaborate
++ hardware features or software to deinterlace and create progressive
++ output frames from a sequence of interlaced input buffers, or it
++ may produce substandard image quality. However, compositors that
++ cannot guarantee reasonable image quality in all cases are recommended
++ to just reject all interlaced buffers.
++
++ Any argument errors, including non-positive width or height,
++ mismatch between the number of planes and the format, bad
++ format, bad offset or stride, may be indicated by fatal protocol
++ errors: INCOMPLETE, INVALID_FORMAT, INVALID_DIMENSIONS,
++ OUT_OF_BOUNDS.
++
++ Dmabuf import errors in the server that are not obvious client
++ bugs are returned via the 'failed' event as non-fatal. This
++ allows attempting dmabuf sharing and falling back in the client
++ if it fails.
++
++ This request can be sent only once in the object's lifetime, after
++ which the only legal request is destroy. This object should be
++ destroyed after issuing a 'create' request. Attempting to use this
++ object after issuing 'create' raises ALREADY_USED protocol error.
++
++ It is not mandatory to issue 'create'. If a client wants to
++ cancel the buffer creation, it can just destroy this object.
++ </description>
++ <arg name="width" type="int" summary="base plane width in pixels"/>
++ <arg name="height" type="int" summary="base plane height in pixels"/>
++ <arg name="format" type="uint" summary="DRM_FORMAT code"/>
++ <arg name="flags" type="uint" enum="flags" summary="see enum flags"/>
++ </request>
++
++ <event name="created">
++ <description summary="buffer creation succeeded">
++ This event indicates that the attempted buffer creation was
++ successful. It provides the new wl_buffer referencing the dmabuf(s).
++
++ Upon receiving this event, the client should destroy the
++ zlinux_dmabuf_params object.
++ </description>
++ <arg name="buffer" type="new_id" interface="wl_buffer"
++ summary="the newly created wl_buffer"/>
++ </event>
++
++ <event name="failed">
++ <description summary="buffer creation failed">
++ This event indicates that the attempted buffer creation has
++ failed. It usually means that one of the dmabuf constraints
++ has not been fulfilled.
++
++ Upon receiving this event, the client should destroy the
++ zlinux_buffer_params object.
++ </description>
++ </event>
++
++ <request name="create_immed" since="2">
++ <description summary="immediately create a wl_buffer from the given
++ dmabufs">
++ This asks for immediate creation of a wl_buffer by importing the
++ added dmabufs.
++
++ In case of import success, no event is sent from the server, and the
++ wl_buffer is ready to be used by the client.
++
++ Upon import failure, either of the following may happen, as seen fit
++ by the implementation:
++ - the client is terminated with one of the following fatal protocol
++ errors:
++ - INCOMPLETE, INVALID_FORMAT, INVALID_DIMENSIONS, OUT_OF_BOUNDS,
++ in case of argument errors such as mismatch between the number
++ of planes and the format, bad format, non-positive width or
++ height, or bad offset or stride.
++ - INVALID_WL_BUFFER, in case the cause for failure is unknown or
++ plaform specific.
++ - the server creates an invalid wl_buffer, marks it as failed and
++ sends a 'failed' event to the client. The result of using this
++ invalid wl_buffer as an argument in any request by the client is
++ defined by the compositor implementation.
++
++ This takes the same arguments as a 'create' request, and obeys the
++ same restrictions.
++ </description>
++ <arg name="buffer_id" type="new_id" interface="wl_buffer"
++ summary="id for the newly created wl_buffer"/>
++ <arg name="width" type="int" summary="base plane width in pixels"/>
++ <arg name="height" type="int" summary="base plane height in pixels"/>
++ <arg name="format" type="uint" summary="DRM_FORMAT code"/>
++ <arg name="flags" type="uint" enum="flags" summary="see enum flags"/>
++ </request>
++ </interface>
++
++ <interface name="zwp_linux_dmabuf_feedback_v1" version="4">
++ <description summary="dmabuf feedback">
++ This object advertises dmabuf parameters feedback. This includes the
++ preferred devices and the supported formats/modifiers.
++
++ The parameters are sent once when this object is created and whenever they
++ change. The done event is always sent once after all parameters have been
++ sent. When a single parameter changes, all parameters are re-sent by the
++ compositor.
++
++ Compositors can re-send the parameters when the current client buffer
++ allocations are sub-optimal. Compositors should not re-send the
++ parameters if re-allocating the buffers would not result in a more optimal
++ configuration. In particular, compositors should avoid sending the exact
++ same parameters multiple times in a row.
++
++ The tranche_target_device and tranche_modifier events are grouped by
++ tranches of preference. For each tranche, a tranche_target_device, one
++ tranche_flags and one or more tranche_modifier events are sent, followed
++ by a tranche_done event finishing the list. The tranches are sent in
++ descending order of preference. All formats and modifiers in the same
++ tranche have the same preference.
++
++ To send parameters, the compositor sends one main_device event, tranches
++ (each consisting of one tranche_target_device event, one tranche_flags
++ event, tranche_modifier events and then a tranche_done event), then one
++ done event.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the feedback object">
++ Using this request a client can tell the server that it is not going to
++ use the wp_linux_dmabuf_feedback object anymore.
++ </description>
++ </request>
++
++ <event name="done">
++ <description summary="all feedback has been sent">
++ This event is sent after all parameters of a wp_linux_dmabuf_feedback
++ object have been sent.
++
++ This allows changes to the wp_linux_dmabuf_feedback parameters to be
++ seen as atomic, even if they happen via multiple events.
++ </description>
++ </event>
++
++ <event name="format_table">
++ <description summary="format and modifier table">
++ This event provides a file descriptor which can be memory-mapped to
++ access the format and modifier table.
++
++ The table contains a tightly packed array of consecutive format +
++ modifier pairs. Each pair is 16 bytes wide. It contains a format as a
++ 32-bit unsigned integer, followed by 4 bytes of unused padding, and a
++ modifier as a 64-bit unsigned integer. The native endianness is used.
++
++ The client must map the file descriptor in read-only private mode.
++
++ Compositors are not allowed to mutate the table file contents once this
++ event has been sent. Instead, compositors must create a new, separate
++ table file and re-send feedback parameters. Compositors are allowed to
++ store duplicate format + modifier pairs in the table.
++ </description>
++ <arg name="fd" type="fd" summary="table file descriptor"/>
++ <arg name="size" type="uint" summary="table size, in bytes"/>
++ </event>
++
++ <event name="main_device">
++ <description summary="preferred main device">
++ This event advertises the main device that the server prefers to use
++ when direct scan-out to the target device isn't possible. The
++ advertised main device may be different for each
++ wp_linux_dmabuf_feedback object, and may change over time.
++
++ There is exactly one main device. The compositor must send at least
++ one preference tranche with tranche_target_device equal to main_device.
++
++ Clients need to create buffers that the main device can import and
++ read from, otherwise creating the dmabuf wl_buffer will fail (see the
++ wp_linux_buffer_params.create and create_immed requests for details).
++ The main device will also likely be kept active by the compositor,
++ so clients can use it instead of waking up another device for power
++ savings.
++
++ In general the device is a DRM node. The DRM node type (primary vs.
++ render) is unspecified. Clients must not rely on the compositor sending
++ a particular node type. Clients cannot check two devices for equality
++ by comparing the dev_t value.
++
++ If explicit modifiers are not supported and the client performs buffer
++ allocations on a different device than the main device, then the client
++ must force the buffer to have a linear layout.
++ </description>
++ <arg name="device" type="array" summary="device dev_t value"/>
++ </event>
++
++ <event name="tranche_done">
++ <description summary="a preference tranche has been sent">
++ This event splits tranche_target_device and tranche_modifier events in
++ preference tranches. It is sent after a set of tranche_target_device
++ and tranche_modifier events; it represents the end of a tranche. The
++ next tranche will have a lower preference.
++ </description>
++ </event>
++
++ <event name="tranche_target_device">
++ <description summary="target device">
++ This event advertises the target device that the server prefers to use
++ for a buffer created given this tranche. The advertised target device
++ may be different for each preference tranche, and may change over time.
++
++ There is exactly one target device per tranche.
++
++ The target device may be a scan-out device, for example if the
++ compositor prefers to directly scan-out a buffer created given this
++ tranche. The target device may be a rendering device, for example if
++ the compositor prefers to texture from said buffer.
++
++ The client can use this hint to allocate the buffer in a way that makes
++ it accessible from the target device, ideally directly. The buffer must
++ still be accessible from the main device, either through direct import
++ or through a potentially more expensive fallback path. If the buffer
++ can't be directly imported from the main device then clients must be
++ prepared for the compositor changing the tranche priority or making
++ wl_buffer creation fail (see the wp_linux_buffer_params.create and
++ create_immed requests for details).
++
++ If the device is a DRM node, the DRM node type (primary vs. render) is
++ unspecified. Clients must not rely on the compositor sending a
++ particular node type. Clients cannot check two devices for equality by
++ comparing the dev_t value.
++
++ This event is tied to a preference tranche, see the tranche_done event.
++ </description>
++ <arg name="device" type="array" summary="device dev_t value"/>
++ </event>
++
++ <event name="tranche_formats">
++ <description summary="supported buffer format modifier">
++ This event advertises the format + modifier combinations that the
++ compositor supports.
++
++ It carries an array of indices, each referring to a format + modifier
++ pair in the last received format table (see the format_table event).
++ Each index is a 16-bit unsigned integer in native endianness.
++
++ For legacy support, DRM_FORMAT_MOD_INVALID is an allowed modifier.
++ It indicates that the server can support the format with an implicit
++ modifier. When a buffer has DRM_FORMAT_MOD_INVALID as its modifier, it
++ is as if no explicit modifier is specified. The effective modifier
++ will be derived from the dmabuf.
++
++ A compositor that sends valid modifiers and DRM_FORMAT_MOD_INVALID for
++ a given format supports both explicit modifiers and implicit modifiers.
++
++ Compositors must not send duplicate format + modifier pairs within the
++ same tranche or across two different tranches with the same target
++ device and flags.
++
++ This event is tied to a preference tranche, see the tranche_done event.
++
++ For the definition of the format and modifier codes, see the
++ wp_linux_buffer_params.create request.
++ </description>
++ <arg name="indices" type="array" summary="array of 16-bit indexes"/>
++ </event>
++
++ <enum name="tranche_flags" bitfield="true">
++ <entry name="scanout" value="1" summary="direct scan-out tranche"/>
++ </enum>
++
++ <event name="tranche_flags">
++ <description summary="tranche flags">
++ This event sets tranche-specific flags.
++
++ The scanout flag is a hint that direct scan-out may be attempted by the
++ compositor on the target device if the client appropriately allocates a
++ buffer. How to allocate a buffer that can be scanned out on the target
++ device is implementation-defined.
++
++ This event is tied to a preference tranche, see the tranche_done event.
++ </description>
++ <arg name="flags" type="uint" enum="tranche_flags" summary="tranche flags"/>
++ </event>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++Linux explicit synchronization (dma-fence) protocol
++
++Maintainers:
++Daniel Stone <daniels@collabora.com>
++Alexandros Frantzis <alexandros.frantzis@collabora.com>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="zwp_linux_explicit_synchronization_unstable_v1">
++
++ <copyright>
++ Copyright 2016 The Chromium Authors.
++ Copyright 2017 Intel Corporation
++ Copyright 2018 Collabora, Ltd
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="zwp_linux_explicit_synchronization_v1" version="2">
++ <description summary="protocol for providing explicit synchronization">
++ This global is a factory interface, allowing clients to request
++ explicit synchronization for buffers on a per-surface basis.
++
++ See zwp_linux_surface_synchronization_v1 for more information.
++
++ This interface is derived from Chromium's
++ zcr_linux_explicit_synchronization_v1.
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible changes
++ may be added together with the corresponding interface version bump.
++ Backward incompatible changes are done by bumping the version number in
++ the protocol and interface names and resetting the interface version.
++ Once the protocol is to be declared stable, the 'z' prefix and the
++ version number in the protocol and interface names are removed and the
++ interface version number is reset.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy explicit synchronization factory object">
++ Destroy this explicit synchronization factory object. Other objects,
++ including zwp_linux_surface_synchronization_v1 objects created by this
++ factory, shall not be affected by this request.
++ </description>
++ </request>
++
++ <enum name="error">
++ <entry name="synchronization_exists" value="0"
++ summary="the surface already has a synchronization object associated"/>
++ </enum>
++
++ <request name="get_synchronization">
++ <description summary="extend surface interface for explicit synchronization">
++ Instantiate an interface extension for the given wl_surface to provide
++ explicit synchronization.
++
++ If the given wl_surface already has an explicit synchronization object
++ associated, the synchronization_exists protocol error is raised.
++
++ Graphics APIs, like EGL or Vulkan, that manage the buffer queue and
++ commits of a wl_surface themselves, are likely to be using this
++ extension internally. If a client is using such an API for a
++ wl_surface, it should not directly use this extension on that surface,
++ to avoid raising a synchronization_exists protocol error.
++ </description>
++
++ <arg name="id" type="new_id"
++ interface="zwp_linux_surface_synchronization_v1"
++ summary="the new synchronization interface id"/>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="the surface"/>
++ </request>
++ </interface>
++
++ <interface name="zwp_linux_surface_synchronization_v1" version="2">
++ <description summary="per-surface explicit synchronization support">
++ This object implements per-surface explicit synchronization.
++
++ Synchronization refers to co-ordination of pipelined operations performed
++ on buffers. Most GPU clients will schedule an asynchronous operation to
++ render to the buffer, then immediately send the buffer to the compositor
++ to be attached to a surface.
++
++ In implicit synchronization, ensuring that the rendering operation is
++ complete before the compositor displays the buffer is an implementation
++ detail handled by either the kernel or userspace graphics driver.
++
++ By contrast, in explicit synchronization, dma_fence objects mark when the
++ asynchronous operations are complete. When submitting a buffer, the
++ client provides an acquire fence which will be waited on before the
++ compositor accesses the buffer. The Wayland server, through a
++ zwp_linux_buffer_release_v1 object, will inform the client with an event
++ which may be accompanied by a release fence, when the compositor will no
++ longer access the buffer contents due to the specific commit that
++ requested the release event.
++
++ Each surface can be associated with only one object of this interface at
++ any time.
++
++ In version 1 of this interface, explicit synchronization is only
++ guaranteed to be supported for buffers created with any version of the
++ wp_linux_dmabuf buffer factory. Version 2 additionally guarantees
++ explicit synchronization support for opaque EGL buffers, which is a type
++ of platform specific buffers described in the EGL_WL_bind_wayland_display
++ extension. Compositors are free to support explicit synchronization for
++ additional buffer types.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy synchronization object">
++ Destroy this explicit synchronization object.
++
++ Any fence set by this object with set_acquire_fence since the last
++ commit will be discarded by the server. Any fences set by this object
++ before the last commit are not affected.
++
++ zwp_linux_buffer_release_v1 objects created by this object are not
++ affected by this request.
++ </description>
++ </request>
++
++ <enum name="error">
++ <entry name="invalid_fence" value="0"
++ summary="the fence specified by the client could not be imported"/>
++ <entry name="duplicate_fence" value="1"
++ summary="multiple fences added for a single surface commit"/>
++ <entry name="duplicate_release" value="2"
++ summary="multiple releases added for a single surface commit"/>
++ <entry name="no_surface" value="3"
++ summary="the associated wl_surface was destroyed"/>
++ <entry name="unsupported_buffer" value="4"
++ summary="the buffer does not support explicit synchronization"/>
++ <entry name="no_buffer" value="5"
++ summary="no buffer was attached"/>
++ </enum>
++
++ <request name="set_acquire_fence">
++ <description summary="set the acquire fence">
++ Set the acquire fence that must be signaled before the compositor
++ may sample from the buffer attached with wl_surface.attach. The fence
++ is a dma_fence kernel object.
++
++ The acquire fence is double-buffered state, and will be applied on the
++ next wl_surface.commit request for the associated surface. Thus, it
++ applies only to the buffer that is attached to the surface at commit
++ time.
++
++ If the provided fd is not a valid dma_fence fd, then an INVALID_FENCE
++ error is raised.
++
++ If a fence has already been attached during the same commit cycle, a
++ DUPLICATE_FENCE error is raised.
++
++ If the associated wl_surface was destroyed, a NO_SURFACE error is
++ raised.
++
++ If at surface commit time the attached buffer does not support explicit
++ synchronization, an UNSUPPORTED_BUFFER error is raised.
++
++ If at surface commit time there is no buffer attached, a NO_BUFFER
++ error is raised.
++ </description>
++ <arg name="fd" type="fd" summary="acquire fence fd"/>
++ </request>
++
++ <request name="get_release">
++ <description summary="release fence for last-attached buffer">
++ Create a listener for the release of the buffer attached by the
++ client with wl_surface.attach. See zwp_linux_buffer_release_v1
++ documentation for more information.
++
++ The release object is double-buffered state, and will be associated
++ with the buffer that is attached to the surface at wl_surface.commit
++ time.
++
++ If a zwp_linux_buffer_release_v1 object has already been requested for
++ the surface in the same commit cycle, a DUPLICATE_RELEASE error is
++ raised.
++
++ If the associated wl_surface was destroyed, a NO_SURFACE error
++ is raised.
++
++ If at surface commit time there is no buffer attached, a NO_BUFFER
++ error is raised.
++ </description>
++ <arg name="release" type="new_id" interface="zwp_linux_buffer_release_v1"
++ summary="new zwp_linux_buffer_release_v1 object"/>
++ </request>
++ </interface>
++
++ <interface name="zwp_linux_buffer_release_v1" version="1">
++ <description summary="buffer release explicit synchronization">
++ This object is instantiated in response to a
++ zwp_linux_surface_synchronization_v1.get_release request.
++
++ It provides an alternative to wl_buffer.release events, providing a
++ unique release from a single wl_surface.commit request. The release event
++ also supports explicit synchronization, providing a fence FD for the
++ client to synchronize against.
++
++ Exactly one event, either a fenced_release or an immediate_release, will
++ be emitted for the wl_surface.commit request. The compositor can choose
++ release by release which event it uses.
++
++ This event does not replace wl_buffer.release events; servers are still
++ required to send those events.
++
++ Once a buffer release object has delivered a 'fenced_release' or an
++ 'immediate_release' event it is automatically destroyed.
++ </description>
++
++ <event name="fenced_release" type="destructor">
++ <description summary="release buffer with fence">
++ Sent when the compositor has finalised its usage of the associated
++ buffer for the relevant commit, providing a dma_fence which will be
++ signaled when all operations by the compositor on that buffer for that
++ commit have finished.
++
++ Once the fence has signaled, and assuming the associated buffer is not
++ pending release from other wl_surface.commit requests, no additional
++ explicit or implicit synchronization is required to safely reuse or
++ destroy the buffer.
++
++ This event destroys the zwp_linux_buffer_release_v1 object.
++ </description>
++ <arg name="fence" type="fd" summary="fence for last operation on buffer"/>
++ </event>
++
++ <event name="immediate_release" type="destructor">
++ <description summary="release buffer immediately">
++ Sent when the compositor has finalised its usage of the associated
++ buffer for the relevant commit, and either performed no operations
++ using it, or has a guarantee that all its operations on that buffer for
++ that commit have finished.
++
++ Once this event is received, and assuming the associated buffer is not
++ pending release from other wl_surface.commit requests, no additional
++ explicit or implicit synchronization is required to safely reuse or
++ destroy the buffer.
++
++ This event destroys the zwp_linux_buffer_release_v1 object.
++ </description>
++ </event>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++Pointer constraints protocol
++
++Maintainers:
++Jonas Ådahl <jadahl@gmail.com>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="pointer_constraints_unstable_v1">
++
++ <copyright>
++ Copyright © 2014 Jonas Ådahl
++ Copyright © 2015 Red Hat Inc.
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <description summary="protocol for constraining pointer motions">
++ This protocol specifies a set of interfaces used for adding constraints to
++ the motion of a pointer. Possible constraints include confining pointer
++ motions to a given region, or locking it to its current position.
++
++ In order to constrain the pointer, a client must first bind the global
++ interface "wp_pointer_constraints" which, if a compositor supports pointer
++ constraints, is exposed by the registry. Using the bound global object, the
++ client uses the request that corresponds to the type of constraint it wants
++ to make. See wp_pointer_constraints for more details.
++
++ Warning! The protocol described in this file is experimental and backward
++ incompatible changes may be made. Backward compatible changes may be added
++ together with the corresponding interface version bump. Backward
++ incompatible changes are done by bumping the version number in the protocol
++ and interface names and resetting the interface version. Once the protocol
++ is to be declared stable, the 'z' prefix and the version number in the
++ protocol and interface names are removed and the interface version number is
++ reset.
++ </description>
++
++ <interface name="zwp_pointer_constraints_v1" version="1">
++ <description summary="constrain the movement of a pointer">
++ The global interface exposing pointer constraining functionality. It
++ exposes two requests: lock_pointer for locking the pointer to its
++ position, and confine_pointer for locking the pointer to a region.
++
++ The lock_pointer and confine_pointer requests create the objects
++ wp_locked_pointer and wp_confined_pointer respectively, and the client can
++ use these objects to interact with the lock.
++
++ For any surface, only one lock or confinement may be active across all
++ wl_pointer objects of the same seat. If a lock or confinement is requested
++ when another lock or confinement is active or requested on the same surface
++ and with any of the wl_pointer objects of the same seat, an
++ 'already_constrained' error will be raised.
++ </description>
++
++ <enum name="error">
++ <description summary="wp_pointer_constraints error values">
++ These errors can be emitted in response to wp_pointer_constraints
++ requests.
++ </description>
++ <entry name="already_constrained" value="1"
++ summary="pointer constraint already requested on that surface"/>
++ </enum>
++
++ <enum name="lifetime">
++ <description summary="constraint lifetime">
++ These values represent different lifetime semantics. They are passed
++ as arguments to the factory requests to specify how the constraint
++ lifetimes should be managed.
++ </description>
++ <entry name="oneshot" value="1">
++ <description summary="the pointer constraint is defunct once deactivated">
++ A oneshot pointer constraint will never reactivate once it has been
++ deactivated. See the corresponding deactivation event
++ (wp_locked_pointer.unlocked and wp_confined_pointer.unconfined) for
++ details.
++ </description>
++ </entry>
++ <entry name="persistent" value="2">
++ <description summary="the pointer constraint may reactivate">
++ A persistent pointer constraint may again reactivate once it has
++ been deactivated. See the corresponding deactivation event
++ (wp_locked_pointer.unlocked and wp_confined_pointer.unconfined) for
++ details.
++ </description>
++ </entry>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the pointer constraints manager object">
++ Used by the client to notify the server that it will no longer use this
++ pointer constraints object.
++ </description>
++ </request>
++
++ <request name="lock_pointer">
++ <description summary="lock pointer to a position">
++ The lock_pointer request lets the client request to disable movements of
++ the virtual pointer (i.e. the cursor), effectively locking the pointer
++ to a position. This request may not take effect immediately; in the
++ future, when the compositor deems implementation-specific constraints
++ are satisfied, the pointer lock will be activated and the compositor
++ sends a locked event.
++
++ The protocol provides no guarantee that the constraints are ever
++ satisfied, and does not require the compositor to send an error if the
++ constraints cannot ever be satisfied. It is thus possible to request a
++ lock that will never activate.
++
++ There may not be another pointer constraint of any kind requested or
++ active on the surface for any of the wl_pointer objects of the seat of
++ the passed pointer when requesting a lock. If there is, an error will be
++ raised. See general pointer lock documentation for more details.
++
++ The intersection of the region passed with this request and the input
++ region of the surface is used to determine where the pointer must be
++ in order for the lock to activate. It is up to the compositor whether to
++ warp the pointer or require some kind of user interaction for the lock
++ to activate. If the region is null the surface input region is used.
++
++ A surface may receive pointer focus without the lock being activated.
++
++ The request creates a new object wp_locked_pointer which is used to
++ interact with the lock as well as receive updates about its state. See
++ the the description of wp_locked_pointer for further information.
++
++ Note that while a pointer is locked, the wl_pointer objects of the
++ corresponding seat will not emit any wl_pointer.motion events, but
++ relative motion events will still be emitted via wp_relative_pointer
++ objects of the same seat. wl_pointer.axis and wl_pointer.button events
++ are unaffected.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_locked_pointer_v1"/>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="surface to lock pointer to"/>
++ <arg name="pointer" type="object" interface="wl_pointer"
++ summary="the pointer that should be locked"/>
++ <arg name="region" type="object" interface="wl_region" allow-null="true"
++ summary="region of surface"/>
++ <arg name="lifetime" type="uint" enum="lifetime" summary="lock lifetime"/>
++ </request>
++
++ <request name="confine_pointer">
++ <description summary="confine pointer to a region">
++ The confine_pointer request lets the client request to confine the
++ pointer cursor to a given region. This request may not take effect
++ immediately; in the future, when the compositor deems implementation-
++ specific constraints are satisfied, the pointer confinement will be
++ activated and the compositor sends a confined event.
++
++ The intersection of the region passed with this request and the input
++ region of the surface is used to determine where the pointer must be
++ in order for the confinement to activate. It is up to the compositor
++ whether to warp the pointer or require some kind of user interaction for
++ the confinement to activate. If the region is null the surface input
++ region is used.
++
++ The request will create a new object wp_confined_pointer which is used
++ to interact with the confinement as well as receive updates about its
++ state. See the the description of wp_confined_pointer for further
++ information.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_confined_pointer_v1"/>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="surface to lock pointer to"/>
++ <arg name="pointer" type="object" interface="wl_pointer"
++ summary="the pointer that should be confined"/>
++ <arg name="region" type="object" interface="wl_region" allow-null="true"
++ summary="region of surface"/>
++ <arg name="lifetime" type="uint" enum="lifetime" summary="confinement lifetime"/>
++ </request>
++ </interface>
++
++ <interface name="zwp_locked_pointer_v1" version="1">
++ <description summary="receive relative pointer motion events">
++ The wp_locked_pointer interface represents a locked pointer state.
++
++ While the lock of this object is active, the wl_pointer objects of the
++ associated seat will not emit any wl_pointer.motion events.
++
++ This object will send the event 'locked' when the lock is activated.
++ Whenever the lock is activated, it is guaranteed that the locked surface
++ will already have received pointer focus and that the pointer will be
++ within the region passed to the request creating this object.
++
++ To unlock the pointer, send the destroy request. This will also destroy
++ the wp_locked_pointer object.
++
++ If the compositor decides to unlock the pointer the unlocked event is
++ sent. See wp_locked_pointer.unlock for details.
++
++ When unlocking, the compositor may warp the cursor position to the set
++ cursor position hint. If it does, it will not result in any relative
++ motion events emitted via wp_relative_pointer.
++
++ If the surface the lock was requested on is destroyed and the lock is not
++ yet activated, the wp_locked_pointer object is now defunct and must be
++ destroyed.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the locked pointer object">
++ Destroy the locked pointer object. If applicable, the compositor will
++ unlock the pointer.
++ </description>
++ </request>
++
++ <request name="set_cursor_position_hint">
++ <description summary="set the pointer cursor position hint">
++ Set the cursor position hint relative to the top left corner of the
++ surface.
++
++ If the client is drawing its own cursor, it should update the position
++ hint to the position of its own cursor. A compositor may use this
++ information to warp the pointer upon unlock in order to avoid pointer
++ jumps.
++
++ The cursor position hint is double buffered. The new hint will only take
++ effect when the associated surface gets it pending state applied. See
++ wl_surface.commit for details.
++ </description>
++ <arg name="surface_x" type="fixed"
++ summary="surface-local x coordinate"/>
++ <arg name="surface_y" type="fixed"
++ summary="surface-local y coordinate"/>
++ </request>
++
++ <request name="set_region">
++ <description summary="set a new lock region">
++ Set a new region used to lock the pointer.
++
++ The new lock region is double-buffered. The new lock region will
++ only take effect when the associated surface gets its pending state
++ applied. See wl_surface.commit for details.
++
++ For details about the lock region, see wp_locked_pointer.
++ </description>
++ <arg name="region" type="object" interface="wl_region" allow-null="true"
++ summary="region of surface"/>
++ </request>
++
++ <event name="locked">
++ <description summary="lock activation event">
++ Notification that the pointer lock of the seat's pointer is activated.
++ </description>
++ </event>
++
++ <event name="unlocked">
++ <description summary="lock deactivation event">
++ Notification that the pointer lock of the seat's pointer is no longer
++ active. If this is a oneshot pointer lock (see
++ wp_pointer_constraints.lifetime) this object is now defunct and should
++ be destroyed. If this is a persistent pointer lock (see
++ wp_pointer_constraints.lifetime) this pointer lock may again
++ reactivate in the future.
++ </description>
++ </event>
++ </interface>
++
++ <interface name="zwp_confined_pointer_v1" version="1">
++ <description summary="confined pointer object">
++ The wp_confined_pointer interface represents a confined pointer state.
++
++ This object will send the event 'confined' when the confinement is
++ activated. Whenever the confinement is activated, it is guaranteed that
++ the surface the pointer is confined to will already have received pointer
++ focus and that the pointer will be within the region passed to the request
++ creating this object. It is up to the compositor to decide whether this
++ requires some user interaction and if the pointer will warp to within the
++ passed region if outside.
++
++ To unconfine the pointer, send the destroy request. This will also destroy
++ the wp_confined_pointer object.
++
++ If the compositor decides to unconfine the pointer the unconfined event is
++ sent. The wp_confined_pointer object is at this point defunct and should
++ be destroyed.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the confined pointer object">
++ Destroy the confined pointer object. If applicable, the compositor will
++ unconfine the pointer.
++ </description>
++ </request>
++
++ <request name="set_region">
++ <description summary="set a new confine region">
++ Set a new region used to confine the pointer.
++
++ The new confine region is double-buffered. The new confine region will
++ only take effect when the associated surface gets its pending state
++ applied. See wl_surface.commit for details.
++
++ If the confinement is active when the new confinement region is applied
++ and the pointer ends up outside of newly applied region, the pointer may
++ warped to a position within the new confinement region. If warped, a
++ wl_pointer.motion event will be emitted, but no
++ wp_relative_pointer.relative_motion event.
++
++ The compositor may also, instead of using the new region, unconfine the
++ pointer.
++
++ For details about the confine region, see wp_confined_pointer.
++ </description>
++ <arg name="region" type="object" interface="wl_region" allow-null="true"
++ summary="region of surface"/>
++ </request>
++
++ <event name="confined">
++ <description summary="pointer confined">
++ Notification that the pointer confinement of the seat's pointer is
++ activated.
++ </description>
++ </event>
++
++ <event name="unconfined">
++ <description summary="pointer unconfined">
++ Notification that the pointer confinement of the seat's pointer is no
++ longer active. If this is a oneshot pointer confinement (see
++ wp_pointer_constraints.lifetime) this object is now defunct and should
++ be destroyed. If this is a persistent pointer confinement (see
++ wp_pointer_constraints.lifetime) this pointer confinement may again
++ reactivate in the future.
++ </description>
++ </event>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++Pointer gestures protocol
++
++Maintainers:
++Carlos Garnacho <carlosg@gnome.org>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="pointer_gestures_unstable_v1">
++
++ <interface name="zwp_pointer_gestures_v1" version="3">
++ <description summary="touchpad gestures">
++ A global interface to provide semantic touchpad gestures for a given
++ pointer.
++
++ Three gestures are currently supported: swipe, pinch, and hold.
++ Pinch and swipe gestures follow a three-stage cycle: begin, update,
++ end, hold gestures follow a two-stage cycle: begin and end. All
++ gestures are identified by a unique id.
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible changes
++ may be added together with the corresponding interface version bump.
++ Backward incompatible changes are done by bumping the version number in
++ the protocol and interface names and resetting the interface version.
++ Once the protocol is to be declared stable, the 'z' prefix and the
++ version number in the protocol and interface names are removed and the
++ interface version number is reset.
++ </description>
++
++ <request name="get_swipe_gesture">
++ <description summary="get swipe gesture">
++ Create a swipe gesture object. See the
++ wl_pointer_gesture_swipe interface for details.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_pointer_gesture_swipe_v1"/>
++ <arg name="pointer" type="object" interface="wl_pointer"/>
++ </request>
++
++ <request name="get_pinch_gesture">
++ <description summary="get pinch gesture">
++ Create a pinch gesture object. See the
++ wl_pointer_gesture_pinch interface for details.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_pointer_gesture_pinch_v1"/>
++ <arg name="pointer" type="object" interface="wl_pointer"/>
++ </request>
++
++ <!-- Version 2 additions -->
++
++ <request name="release" type="destructor" since="2">
++ <description summary="destroy the pointer gesture object">
++ Destroy the pointer gesture object. Swipe, pinch and hold objects
++ created via this gesture object remain valid.
++ </description>
++ </request>
++
++ <!-- Version 3 additions -->
++
++ <request name="get_hold_gesture" since="3">
++ <description summary="get hold gesture">
++ Create a hold gesture object. See the
++ wl_pointer_gesture_hold interface for details.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_pointer_gesture_hold_v1"/>
++ <arg name="pointer" type="object" interface="wl_pointer"/>
++ </request>
++
++ </interface>
++
++ <interface name="zwp_pointer_gesture_swipe_v1" version="2">
++ <description summary="a swipe gesture object">
++ A swipe gesture object notifies a client about a multi-finger swipe
++ gesture detected on an indirect input device such as a touchpad.
++ The gesture is usually initiated by multiple fingers moving in the
++ same direction but once initiated the direction may change.
++ The precise conditions of when such a gesture is detected are
++ implementation-dependent.
++
++ A gesture consists of three stages: begin, update (optional) and end.
++ There cannot be multiple simultaneous hold, pinch or swipe gestures on a
++ same pointer/seat, how compositors prevent these situations is
++ implementation-dependent.
++
++ A gesture may be cancelled by the compositor or the hardware.
++ Clients should not consider performing permanent or irreversible
++ actions until the end of a gesture has been received.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the pointer swipe gesture object"/>
++ </request>
++
++ <event name="begin">
++ <description summary="multi-finger swipe begin">
++ This event is sent when a multi-finger swipe gesture is detected
++ on the device.
++ </description>
++ <arg name="serial" type="uint"/>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ <arg name="fingers" type="uint" summary="number of fingers"/>
++ </event>
++
++ <event name="update">
++ <description summary="multi-finger swipe motion">
++ This event is sent when a multi-finger swipe gesture changes the
++ position of the logical center.
++
++ The dx and dy coordinates are relative coordinates of the logical
++ center of the gesture compared to the previous event.
++ </description>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="dx" type="fixed" summary="delta x coordinate in surface coordinate space"/>
++ <arg name="dy" type="fixed" summary="delta y coordinate in surface coordinate space"/>
++ </event>
++
++ <event name="end">
++ <description summary="multi-finger swipe end">
++ This event is sent when a multi-finger swipe gesture ceases to
++ be valid. This may happen when one or more fingers are lifted or
++ the gesture is cancelled.
++
++ When a gesture is cancelled, the client should undo state changes
++ caused by this gesture. What causes a gesture to be cancelled is
++ implementation-dependent.
++ </description>
++ <arg name="serial" type="uint"/>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
++ </event>
++ </interface>
++
++ <interface name="zwp_pointer_gesture_pinch_v1" version="2">
++ <description summary="a pinch gesture object">
++ A pinch gesture object notifies a client about a multi-finger pinch
++ gesture detected on an indirect input device such as a touchpad.
++ The gesture is usually initiated by multiple fingers moving towards
++ each other or away from each other, or by two or more fingers rotating
++ around a logical center of gravity. The precise conditions of when
++ such a gesture is detected are implementation-dependent.
++
++ A gesture consists of three stages: begin, update (optional) and end.
++ There cannot be multiple simultaneous hold, pinch or swipe gestures on a
++ same pointer/seat, how compositors prevent these situations is
++ implementation-dependent.
++
++ A gesture may be cancelled by the compositor or the hardware.
++ Clients should not consider performing permanent or irreversible
++ actions until the end of a gesture has been received.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the pinch gesture object"/>
++ </request>
++
++ <event name="begin">
++ <description summary="multi-finger pinch begin">
++ This event is sent when a multi-finger pinch gesture is detected
++ on the device.
++ </description>
++ <arg name="serial" type="uint"/>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ <arg name="fingers" type="uint" summary="number of fingers"/>
++ </event>
++
++ <event name="update">
++ <description summary="multi-finger pinch motion">
++ This event is sent when a multi-finger pinch gesture changes the
++ position of the logical center, the rotation or the relative scale.
++
++ The dx and dy coordinates are relative coordinates in the
++ surface coordinate space of the logical center of the gesture.
++
++ The scale factor is an absolute scale compared to the
++ pointer_gesture_pinch.begin event, e.g. a scale of 2 means the fingers
++ are now twice as far apart as on pointer_gesture_pinch.begin.
++
++ The rotation is the relative angle in degrees clockwise compared to the previous
++ pointer_gesture_pinch.begin or pointer_gesture_pinch.update event.
++ </description>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="dx" type="fixed" summary="delta x coordinate in surface coordinate space"/>
++ <arg name="dy" type="fixed" summary="delta y coordinate in surface coordinate space"/>
++ <arg name="scale" type="fixed" summary="scale relative to the initial finger position"/>
++ <arg name="rotation" type="fixed" summary="angle in degrees cw relative to the previous event"/>
++ </event>
++
++ <event name="end">
++ <description summary="multi-finger pinch end">
++ This event is sent when a multi-finger pinch gesture ceases to
++ be valid. This may happen when one or more fingers are lifted or
++ the gesture is cancelled.
++
++ When a gesture is cancelled, the client should undo state changes
++ caused by this gesture. What causes a gesture to be cancelled is
++ implementation-dependent.
++ </description>
++ <arg name="serial" type="uint"/>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
++ </event>
++
++ </interface>
++
++ <interface name="zwp_pointer_gesture_hold_v1" version="3">
++ <description summary="a hold gesture object">
++ A hold gesture object notifies a client about a single- or
++ multi-finger hold gesture detected on an indirect input device such as
++ a touchpad. The gesture is usually initiated by one or more fingers
++ being held down without significant movement. The precise conditions
++ of when such a gesture is detected are implementation-dependent.
++
++ In particular, this gesture may be used to cancel kinetic scrolling.
++
++ A hold gesture consists of two stages: begin and end. Unlike pinch and
++ swipe there is no update stage.
++ There cannot be multiple simultaneous hold, pinch or swipe gestures on a
++ same pointer/seat, how compositors prevent these situations is
++ implementation-dependent.
++
++ A gesture may be cancelled by the compositor or the hardware.
++ Clients should not consider performing permanent or irreversible
++ actions until the end of a gesture has been received.
++ </description>
++
++ <request name="destroy" type="destructor" since="3">
++ <description summary="destroy the hold gesture object"/>
++ </request>
++
++ <event name="begin" since="3">
++ <description summary="multi-finger hold begin">
++ This event is sent when a hold gesture is detected on the device.
++ </description>
++ <arg name="serial" type="uint"/>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ <arg name="fingers" type="uint" summary="number of fingers"/>
++ </event>
++
++ <event name="end" since="3">
++ <description summary="multi-finger hold end">
++ This event is sent when a hold gesture ceases to
++ be valid. This may happen when the holding fingers are lifted or
++ the gesture is cancelled, for example if the fingers move past an
++ implementation-defined threshold, the finger count changes or the hold
++ gesture changes into a different type of gesture.
++
++ When a gesture is cancelled, the client may need to undo state changes
++ caused by this gesture. What causes a gesture to be cancelled is
++ implementation-dependent.
++ </description>
++ <arg name="serial" type="uint"/>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
++ </event>
++
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++Primary selection protocol
++
++Maintainers:
++Simon Ser <contact@emersion.fr>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="wp_primary_selection_unstable_v1">
++ <copyright>
++ Copyright © 2015, 2016 Red Hat
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <description summary="Primary selection protocol">
++ This protocol provides the ability to have a primary selection device to
++ match that of the X server. This primary selection is a shortcut to the
++ common clipboard selection, where text just needs to be selected in order
++ to allow copying it elsewhere. The de facto way to perform this action
++ is the middle mouse button, although it is not limited to this one.
++
++ Clients wishing to honor primary selection should create a primary
++ selection source and set it as the selection through
++ wp_primary_selection_device.set_selection whenever the text selection
++ changes. In order to minimize calls in pointer-driven text selection,
++ it should happen only once after the operation finished. Similarly,
++ a NULL source should be set when text is unselected.
++
++ wp_primary_selection_offer objects are first announced through the
++ wp_primary_selection_device.data_offer event. Immediately after this event,
++ the primary data offer will emit wp_primary_selection_offer.offer events
++ to let know of the mime types being offered.
++
++ When the primary selection changes, the client with the keyboard focus
++ will receive wp_primary_selection_device.selection events. Only the client
++ with the keyboard focus will receive such events with a non-NULL
++ wp_primary_selection_offer. Across keyboard focus changes, previously
++ focused clients will receive wp_primary_selection_device.events with a
++ NULL wp_primary_selection_offer.
++
++ In order to request the primary selection data, the client must pass
++ a recent serial pertaining to the press event that is triggering the
++ operation, if the compositor deems the serial valid and recent, the
++ wp_primary_selection_source.send event will happen in the other end
++ to let the transfer begin. The client owning the primary selection
++ should write the requested data, and close the file descriptor
++ immediately.
++
++ If the primary selection owner client disappeared during the transfer,
++ the client reading the data will receive a
++ wp_primary_selection_device.selection event with a NULL
++ wp_primary_selection_offer, the client should take this as a hint
++ to finish the reads related to the no longer existing offer.
++
++ The primary selection owner should be checking for errors during
++ writes, merely cancelling the ongoing transfer if any happened.
++ </description>
++
++ <interface name="zwp_primary_selection_device_manager_v1" version="1">
++ <description summary="X primary selection emulation">
++ The primary selection device manager is a singleton global object that
++ provides access to the primary selection. It allows to create
++ wp_primary_selection_source objects, as well as retrieving the per-seat
++ wp_primary_selection_device objects.
++ </description>
++
++ <request name="create_source">
++ <description summary="create a new primary selection source">
++ Create a new primary selection source.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_primary_selection_source_v1"/>
++ </request>
++
++ <request name="get_device">
++ <description summary="create a new primary selection device">
++ Create a new data device for a given seat.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_primary_selection_device_v1"/>
++ <arg name="seat" type="object" interface="wl_seat"/>
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the primary selection device manager">
++ Destroy the primary selection device manager.
++ </description>
++ </request>
++ </interface>
++
++ <interface name="zwp_primary_selection_device_v1" version="1">
++ <request name="set_selection">
++ <description summary="set the primary selection">
++ Replaces the current selection. The previous owner of the primary
++ selection will receive a wp_primary_selection_source.cancelled event.
++
++ To unset the selection, set the source to NULL.
++ </description>
++ <arg name="source" type="object" interface="zwp_primary_selection_source_v1" allow-null="true"/>
++ <arg name="serial" type="uint" summary="serial of the event that triggered this request"/>
++ </request>
++
++ <event name="data_offer">
++ <description summary="introduce a new wp_primary_selection_offer">
++ Introduces a new wp_primary_selection_offer object that may be used
++ to receive the current primary selection. Immediately following this
++ event, the new wp_primary_selection_offer object will send
++ wp_primary_selection_offer.offer events to describe the offered mime
++ types.
++ </description>
++ <arg name="offer" type="new_id" interface="zwp_primary_selection_offer_v1"/>
++ </event>
++
++ <event name="selection">
++ <description summary="advertise a new primary selection">
++ The wp_primary_selection_device.selection event is sent to notify the
++ client of a new primary selection. This event is sent after the
++ wp_primary_selection.data_offer event introducing this object, and after
++ the offer has announced its mimetypes through
++ wp_primary_selection_offer.offer.
++
++ The data_offer is valid until a new offer or NULL is received
++ or until the client loses keyboard focus. The client must destroy the
++ previous selection data_offer, if any, upon receiving this event.
++ </description>
++ <arg name="id" type="object" interface="zwp_primary_selection_offer_v1" allow-null="true"/>
++ </event>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the primary selection device">
++ Destroy the primary selection device.
++ </description>
++ </request>
++ </interface>
++
++ <interface name="zwp_primary_selection_offer_v1" version="1">
++ <description summary="offer to transfer primary selection contents">
++ A wp_primary_selection_offer represents an offer to transfer the contents
++ of the primary selection clipboard to the client. Similar to
++ wl_data_offer, the offer also describes the mime types that the data can
++ be converted to and provides the mechanisms for transferring the data
++ directly to the client.
++ </description>
++
++ <request name="receive">
++ <description summary="request that the data is transferred">
++ To transfer the contents of the primary selection clipboard, the client
++ issues this request and indicates the mime type that it wants to
++ receive. The transfer happens through the passed file descriptor
++ (typically created with the pipe system call). The source client writes
++ the data in the mime type representation requested and then closes the
++ file descriptor.
++
++ The receiving client reads from the read end of the pipe until EOF and
++ closes its end, at which point the transfer is complete.
++ </description>
++ <arg name="mime_type" type="string"/>
++ <arg name="fd" type="fd"/>
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the primary selection offer">
++ Destroy the primary selection offer.
++ </description>
++ </request>
++
++ <event name="offer">
++ <description summary="advertise offered mime type">
++ Sent immediately after creating announcing the
++ wp_primary_selection_offer through
++ wp_primary_selection_device.data_offer. One event is sent per offered
++ mime type.
++ </description>
++ <arg name="mime_type" type="string"/>
++ </event>
++ </interface>
++
++ <interface name="zwp_primary_selection_source_v1" version="1">
++ <description summary="offer to replace the contents of the primary selection">
++ The source side of a wp_primary_selection_offer, it provides a way to
++ describe the offered data and respond to requests to transfer the
++ requested contents of the primary selection clipboard.
++ </description>
++
++ <request name="offer">
++ <description summary="add an offered mime type">
++ This request adds a mime type to the set of mime types advertised to
++ targets. Can be called several times to offer multiple types.
++ </description>
++ <arg name="mime_type" type="string"/>
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the primary selection source">
++ Destroy the primary selection source.
++ </description>
++ </request>
++
++ <event name="send">
++ <description summary="send the primary selection contents">
++ Request for the current primary selection contents from the client.
++ Send the specified mime type over the passed file descriptor, then
++ close it.
++ </description>
++ <arg name="mime_type" type="string"/>
++ <arg name="fd" type="fd"/>
++ </event>
++
++ <event name="cancelled">
++ <description summary="request for primary selection contents was canceled">
++ This primary selection source is no longer valid. The client should
++ clean up and destroy this primary selection source.
++ </description>
++ </event>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++Relative pointer protocol
++
++Maintainers:
++Jonas Ådahl <jadahl@gmail.com>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="relative_pointer_unstable_v1">
++
++ <copyright>
++ Copyright © 2014 Jonas Ådahl
++ Copyright © 2015 Red Hat Inc.
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <description summary="protocol for relative pointer motion events">
++ This protocol specifies a set of interfaces used for making clients able to
++ receive relative pointer events not obstructed by barriers (such as the
++ monitor edge or other pointer barriers).
++
++ To start receiving relative pointer events, a client must first bind the
++ global interface "wp_relative_pointer_manager" which, if a compositor
++ supports relative pointer motion events, is exposed by the registry. After
++ having created the relative pointer manager proxy object, the client uses
++ it to create the actual relative pointer object using the
++ "get_relative_pointer" request given a wl_pointer. The relative pointer
++ motion events will then, when applicable, be transmitted via the proxy of
++ the newly created relative pointer object. See the documentation of the
++ relative pointer interface for more details.
++
++ Warning! The protocol described in this file is experimental and backward
++ incompatible changes may be made. Backward compatible changes may be added
++ together with the corresponding interface version bump. Backward
++ incompatible changes are done by bumping the version number in the protocol
++ and interface names and resetting the interface version. Once the protocol
++ is to be declared stable, the 'z' prefix and the version number in the
++ protocol and interface names are removed and the interface version number is
++ reset.
++ </description>
++
++ <interface name="zwp_relative_pointer_manager_v1" version="1">
++ <description summary="get relative pointer objects">
++ A global interface used for getting the relative pointer object for a
++ given pointer.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the relative pointer manager object">
++ Used by the client to notify the server that it will no longer use this
++ relative pointer manager object.
++ </description>
++ </request>
++
++ <request name="get_relative_pointer">
++ <description summary="get a relative pointer object">
++ Create a relative pointer interface given a wl_pointer object. See the
++ wp_relative_pointer interface for more details.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_relative_pointer_v1"/>
++ <arg name="pointer" type="object" interface="wl_pointer"/>
++ </request>
++ </interface>
++
++ <interface name="zwp_relative_pointer_v1" version="1">
++ <description summary="relative pointer object">
++ A wp_relative_pointer object is an extension to the wl_pointer interface
++ used for emitting relative pointer events. It shares the same focus as
++ wl_pointer objects of the same seat and will only emit events when it has
++ focus.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="release the relative pointer object"/>
++ </request>
++
++ <event name="relative_motion">
++ <description summary="relative pointer motion">
++ Relative x/y pointer motion from the pointer of the seat associated with
++ this object.
++
++ A relative motion is in the same dimension as regular wl_pointer motion
++ events, except they do not represent an absolute position. For example,
++ moving a pointer from (x, y) to (x', y') would have the equivalent
++ relative motion (x' - x, y' - y). If a pointer motion caused the
++ absolute pointer position to be clipped by for example the edge of the
++ monitor, the relative motion is unaffected by the clipping and will
++ represent the unclipped motion.
++
++ This event also contains non-accelerated motion deltas. The
++ non-accelerated delta is, when applicable, the regular pointer motion
++ delta as it was before having applied motion acceleration and other
++ transformations such as normalization.
++
++ Note that the non-accelerated delta does not represent 'raw' events as
++ they were read from some device. Pointer motion acceleration is device-
++ and configuration-specific and non-accelerated deltas and accelerated
++ deltas may have the same value on some devices.
++
++ Relative motions are not coupled to wl_pointer.motion events, and can be
++ sent in combination with such events, but also independently. There may
++ also be scenarios where wl_pointer.motion is sent, but there is no
++ relative motion. The order of an absolute and relative motion event
++ originating from the same physical motion is not guaranteed.
++
++ If the client needs button events or focus state, it can receive them
++ from a wl_pointer object of the same seat that the wp_relative_pointer
++ object is associated with.
++ </description>
++ <arg name="utime_hi" type="uint"
++ summary="high 32 bits of a 64 bit timestamp with microsecond granularity"/>
++ <arg name="utime_lo" type="uint"
++ summary="low 32 bits of a 64 bit timestamp with microsecond granularity"/>
++ <arg name="dx" type="fixed"
++ summary="the x component of the motion vector"/>
++ <arg name="dy" type="fixed"
++ summary="the y component of the motion vector"/>
++ <arg name="dx_unaccel" type="fixed"
++ summary="the x component of the unaccelerated motion vector"/>
++ <arg name="dy_unaccel" type="fixed"
++ summary="the y component of the unaccelerated motion vector"/>
++ </event>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++Tablet protocol
++
++Maintainers:
++Peter Hutterer <peter.hutterer@who-t.net>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="tablet_unstable_v1">
++
++ <copyright>
++ Copyright 2014 © Stephen "Lyude" Chandler Paul
++ Copyright 2015-2016 © Red Hat, Inc.
++
++ Permission is hereby granted, free of charge, to any person
++ obtaining a copy of this software and associated documentation files
++ (the "Software"), to deal in the Software without restriction,
++ including without limitation the rights to use, copy, modify, merge,
++ publish, distribute, sublicense, and/or sell copies of the Software,
++ and to permit persons to whom the Software is furnished to do so,
++ subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the
++ next paragraph) shall be included in all copies or substantial
++ portions of the Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ SOFTWARE.
++ </copyright>
++
++ <description summary="Wayland protocol for graphics tablets">
++ This description provides a high-level overview of the interplay between
++ the interfaces defined this protocol. For details, see the protocol
++ specification.
++
++ More than one tablet may exist, and device-specifics matter. Tablets are
++ not represented by a single virtual device like wl_pointer. A client
++ binds to the tablet manager object which is just a proxy object. From
++ that, the client requests wp_tablet_manager.get_tablet_seat(wl_seat)
++ and that returns the actual interface that has all the tablets. With
++ this indirection, we can avoid merging wp_tablet into the actual Wayland
++ protocol, a long-term benefit.
++
++ The wp_tablet_seat sends a "tablet added" event for each tablet
++ connected. That event is followed by descriptive events about the
++ hardware; currently that includes events for name, vid/pid and
++ a wp_tablet.path event that describes a local path. This path can be
++ used to uniquely identify a tablet or get more information through
++ libwacom. Emulated or nested tablets can skip any of those, e.g. a
++ virtual tablet may not have a vid/pid. The sequence of descriptive
++ events is terminated by a wp_tablet.done event to signal that a client
++ may now finalize any initialization for that tablet.
++
++ Events from tablets require a tool in proximity. Tools are also managed
++ by the tablet seat; a "tool added" event is sent whenever a tool is new
++ to the compositor. That event is followed by a number of descriptive
++ events about the hardware; currently that includes capabilities,
++ hardware id and serial number, and tool type. Similar to the tablet
++ interface, a wp_tablet_tool.done event is sent to terminate that initial
++ sequence.
++
++ Any event from a tool happens on the wp_tablet_tool interface. When the
++ tool gets into proximity of the tablet, a proximity_in event is sent on
++ the wp_tablet_tool interface, listing the tablet and the surface. That
++ event is followed by a motion event with the coordinates. After that,
++ it's the usual motion, axis, button, etc. events. The protocol's
++ serialisation means events are grouped by wp_tablet_tool.frame events.
++
++ Two special events (that don't exist in X) are down and up. They signal
++ "tip touching the surface". For tablets without real proximity
++ detection, the sequence is: proximity_in, motion, down, frame.
++
++ When the tool leaves proximity, a proximity_out event is sent. If any
++ button is still down, a button release event is sent before this
++ proximity event. These button events are sent in the same frame as the
++ proximity event to signal to the client that the buttons were held when
++ the tool left proximity.
++
++ If the tool moves out of the surface but stays in proximity (i.e.
++ between windows), compositor-specific grab policies apply. This usually
++ means that the proximity-out is delayed until all buttons are released.
++
++ Moving a tool physically from one tablet to the other has no real effect
++ on the protocol, since we already have the tool object from the "tool
++ added" event. All the information is already there and the proximity
++ events on both tablets are all a client needs to reconstruct what
++ happened.
++
++ Some extra axes are normalized, i.e. the client knows the range as
++ specified in the protocol (e.g. [0, 65535]), the granularity however is
++ unknown. The current normalized axes are pressure, distance, and slider.
++
++ Other extra axes are in physical units as specified in the protocol.
++ The current extra axes with physical units are tilt, rotation and
++ wheel rotation.
++
++ Since tablets work independently of the pointer controlled by the mouse,
++ the focus handling is independent too and controlled by proximity.
++ The wp_tablet_tool.set_cursor request sets a tool-specific cursor.
++ This cursor surface may be the same as the mouse cursor, and it may be
++ the same across tools but it is possible to be more fine-grained. For
++ example, a client may set different cursors for the pen and eraser.
++
++ Tools are generally independent of tablets and it is
++ compositor-specific policy when a tool can be removed. Common approaches
++ will likely include some form of removing a tool when all tablets the
++ tool was used on are removed.
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible changes
++ may be added together with the corresponding interface version bump.
++ Backward incompatible changes are done by bumping the version number in
++ the protocol and interface names and resetting the interface version.
++ Once the protocol is to be declared stable, the 'z' prefix and the
++ version number in the protocol and interface names are removed and the
++ interface version number is reset.
++ </description>
++
++ <interface name="zwp_tablet_manager_v1" version="1">
++ <description summary="controller object for graphic tablet devices">
++ An object that provides access to the graphics tablets available on this
++ system. All tablets are associated with a seat, to get access to the
++ actual tablets, use wp_tablet_manager.get_tablet_seat.
++ </description>
++
++ <request name="get_tablet_seat">
++ <description summary="get the tablet seat">
++ Get the wp_tablet_seat object for the given seat. This object
++ provides access to all graphics tablets in this seat.
++ </description>
++ <arg name="tablet_seat" type="new_id" interface="zwp_tablet_seat_v1"/>
++ <arg name="seat" type="object" interface="wl_seat" summary="The wl_seat object to retrieve the tablets for" />
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="release the memory for the tablet manager object">
++ Destroy the wp_tablet_manager object. Objects created from this
++ object are unaffected and should be destroyed separately.
++ </description>
++ </request>
++ </interface>
++
++ <interface name="zwp_tablet_seat_v1" version="1">
++ <description summary="controller object for graphic tablet devices of a seat">
++ An object that provides access to the graphics tablets available on this
++ seat. After binding to this interface, the compositor sends a set of
++ wp_tablet_seat.tablet_added and wp_tablet_seat.tool_added events.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="release the memory for the tablet seat object">
++ Destroy the wp_tablet_seat object. Objects created from this
++ object are unaffected and should be destroyed separately.
++ </description>
++ </request>
++
++ <event name="tablet_added">
++ <description summary="new device notification">
++ This event is sent whenever a new tablet becomes available on this
++ seat. This event only provides the object id of the tablet, any
++ static information about the tablet (device name, vid/pid, etc.) is
++ sent through the wp_tablet interface.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_tablet_v1" summary="the newly added graphics tablet"/>
++ </event>
++
++ <event name="tool_added">
++ <description summary="a new tool has been used with a tablet">
++ This event is sent whenever a tool that has not previously been used
++ with a tablet comes into use. This event only provides the object id
++ of the tool; any static information about the tool (capabilities,
++ type, etc.) is sent through the wp_tablet_tool interface.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_tablet_tool_v1" summary="the newly added tablet tool"/>
++ </event>
++ </interface>
++
++ <interface name="zwp_tablet_tool_v1" version="1">
++ <description summary="a physical tablet tool">
++ An object that represents a physical tool that has been, or is
++ currently in use with a tablet in this seat. Each wp_tablet_tool
++ object stays valid until the client destroys it; the compositor
++ reuses the wp_tablet_tool object to indicate that the object's
++ respective physical tool has come into proximity of a tablet again.
++
++ A wp_tablet_tool object's relation to a physical tool depends on the
++ tablet's ability to report serial numbers. If the tablet supports
++ this capability, then the object represents a specific physical tool
++ and can be identified even when used on multiple tablets.
++
++ A tablet tool has a number of static characteristics, e.g. tool type,
++ hardware_serial and capabilities. These capabilities are sent in an
++ event sequence after the wp_tablet_seat.tool_added event before any
++ actual events from this tool. This initial event sequence is
++ terminated by a wp_tablet_tool.done event.
++
++ Tablet tool events are grouped by wp_tablet_tool.frame events.
++ Any events received before a wp_tablet_tool.frame event should be
++ considered part of the same hardware state change.
++ </description>
++
++ <request name="set_cursor">
++ <description summary="set the tablet tool's surface">
++ Sets the surface of the cursor used for this tool on the given
++ tablet. This request only takes effect if the tool is in proximity
++ of one of the requesting client's surfaces or the surface parameter
++ is the current pointer surface. If there was a previous surface set
++ with this request it is replaced. If surface is NULL, the cursor
++ image is hidden.
++
++ The parameters hotspot_x and hotspot_y define the position of the
++ pointer surface relative to the pointer location. Its top-left corner
++ is always at (x, y) - (hotspot_x, hotspot_y), where (x, y) are the
++ coordinates of the pointer location, in surface-local coordinates.
++
++ On surface.attach requests to the pointer surface, hotspot_x and
++ hotspot_y are decremented by the x and y parameters passed to the
++ request. Attach must be confirmed by wl_surface.commit as usual.
++
++ The hotspot can also be updated by passing the currently set pointer
++ surface to this request with new values for hotspot_x and hotspot_y.
++
++ The current and pending input regions of the wl_surface are cleared,
++ and wl_surface.set_input_region is ignored until the wl_surface is no
++ longer used as the cursor. When the use as a cursor ends, the current
++ and pending input regions become undefined, and the wl_surface is
++ unmapped.
++
++ This request gives the surface the role of a cursor. The role
++ assigned by this request is the same as assigned by
++ wl_pointer.set_cursor meaning the same surface can be
++ used both as a wl_pointer cursor and a wp_tablet cursor. If the
++ surface already has another role, it raises a protocol error.
++ The surface may be used on multiple tablets and across multiple
++ seats.
++ </description>
++ <arg name="serial" type="uint" summary="serial of the enter event"/>
++ <arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
++ <arg name="hotspot_x" type="int" summary="surface-local x coordinate"/>
++ <arg name="hotspot_y" type="int" summary="surface-local y coordinate"/>
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the tool object">
++ This destroys the client's resource for this tool object.
++ </description>
++ </request>
++
++ <enum name="type">
++ <description summary="a physical tool type">
++ Describes the physical type of a tool. The physical type of a tool
++ generally defines its base usage.
++
++ The mouse tool represents a mouse-shaped tool that is not a relative
++ device but bound to the tablet's surface, providing absolute
++ coordinates.
++
++ The lens tool is a mouse-shaped tool with an attached lens to
++ provide precision focus.
++ </description>
++ <entry name="pen" value="0x140" summary="Pen"/>
++ <entry name="eraser" value="0x141" summary="Eraser"/>
++ <entry name="brush" value="0x142" summary="Brush"/>
++ <entry name="pencil" value="0x143" summary="Pencil"/>
++ <entry name="airbrush" value="0x144" summary="Airbrush"/>
++ <entry name="finger" value="0x145" summary="Finger"/>
++ <entry name="mouse" value="0x146" summary="Mouse"/>
++ <entry name="lens" value="0x147" summary="Lens"/>
++ </enum>
++
++ <event name="type">
++ <description summary="tool type">
++ The tool type is the high-level type of the tool and usually decides
++ the interaction expected from this tool.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet_tool.done event.
++ </description>
++ <arg name="tool_type" type="uint" enum="type" summary="the physical tool type"/>
++ </event>
++
++ <event name="hardware_serial">
++ <description summary="unique hardware serial number of the tool">
++ If the physical tool can be identified by a unique 64-bit serial
++ number, this event notifies the client of this serial number.
++
++ If multiple tablets are available in the same seat and the tool is
++ uniquely identifiable by the serial number, that tool may move
++ between tablets.
++
++ Otherwise, if the tool has no serial number and this event is
++ missing, the tool is tied to the tablet it first comes into
++ proximity with. Even if the physical tool is used on multiple
++ tablets, separate wp_tablet_tool objects will be created, one per
++ tablet.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet_tool.done event.
++ </description>
++ <arg name="hardware_serial_hi" type="uint" summary="the unique serial number of the tool, most significant bits"/>
++ <arg name="hardware_serial_lo" type="uint" summary="the unique serial number of the tool, least significant bits"/>
++ </event>
++
++ <event name="hardware_id_wacom">
++ <description summary="hardware id notification in Wacom's format">
++ This event notifies the client of a hardware id available on this tool.
++
++ The hardware id is a device-specific 64-bit id that provides extra
++ information about the tool in use, beyond the wl_tool.type
++ enumeration. The format of the id is specific to tablets made by
++ Wacom Inc. For example, the hardware id of a Wacom Grip
++ Pen (a stylus) is 0x802.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet_tool.done event.
++ </description>
++ <arg name="hardware_id_hi" type="uint" summary="the hardware id, most significant bits"/>
++ <arg name="hardware_id_lo" type="uint" summary="the hardware id, least significant bits"/>
++ </event>
++
++ <enum name="capability">
++ <description summary="capability flags for a tool">
++ Describes extra capabilities on a tablet.
++
++ Any tool must provide x and y values, extra axes are
++ device-specific.
++ </description>
++ <entry name="tilt" value="1" summary="Tilt axes"/>
++ <entry name="pressure" value="2" summary="Pressure axis"/>
++ <entry name="distance" value="3" summary="Distance axis"/>
++ <entry name="rotation" value="4" summary="Z-rotation axis"/>
++ <entry name="slider" value="5" summary="Slider axis"/>
++ <entry name="wheel" value="6" summary="Wheel axis"/>
++ </enum>
++
++ <event name="capability">
++ <description summary="tool capability notification">
++ This event notifies the client of any capabilities of this tool,
++ beyond the main set of x/y axes and tip up/down detection.
++
++ One event is sent for each extra capability available on this tool.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet_tool.done event.
++ </description>
++ <arg name="capability" type="uint" enum="capability" summary="the capability"/>
++ </event>
++
++ <event name="done">
++ <description summary="tool description events sequence complete">
++ This event signals the end of the initial burst of descriptive
++ events. A client may consider the static description of the tool to
++ be complete and finalize initialization of the tool.
++ </description>
++ </event>
++
++ <event name="removed">
++ <description summary="tool removed">
++ This event is sent when the tool is removed from the system and will
++ send no further events. Should the physical tool come back into
++ proximity later, a new wp_tablet_tool object will be created.
++
++ It is compositor-dependent when a tool is removed. A compositor may
++ remove a tool on proximity out, tablet removal or any other reason.
++ A compositor may also keep a tool alive until shutdown.
++
++ If the tool is currently in proximity, a proximity_out event will be
++ sent before the removed event. See wp_tablet_tool.proximity_out for
++ the handling of any buttons logically down.
++
++ When this event is received, the client must wp_tablet_tool.destroy
++ the object.
++ </description>
++ </event>
++
++ <event name="proximity_in">
++ <description summary="proximity in event">
++ Notification that this tool is focused on a certain surface.
++
++ This event can be received when the tool has moved from one surface to
++ another, or when the tool has come back into proximity above the
++ surface.
++
++ If any button is logically down when the tool comes into proximity,
++ the respective button event is sent after the proximity_in event but
++ within the same frame as the proximity_in event.
++ </description>
++ <arg name="serial" type="uint"/>
++ <arg name="tablet" type="object" interface="zwp_tablet_v1" summary="The tablet the tool is in proximity of"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="The current surface the tablet tool is over"/>
++ </event>
++
++ <event name="proximity_out">
++ <description summary="proximity out event">
++ Notification that this tool has either left proximity, or is no
++ longer focused on a certain surface.
++
++ When the tablet tool leaves proximity of the tablet, button release
++ events are sent for each button that was held down at the time of
++ leaving proximity. These events are sent before the proximity_out
++ event but within the same wp_tablet.frame.
++
++ If the tool stays within proximity of the tablet, but the focus
++ changes from one surface to another, a button release event may not
++ be sent until the button is actually released or the tool leaves the
++ proximity of the tablet.
++ </description>
++ </event>
++
++ <event name="down">
++ <description summary="tablet tool is making contact">
++ Sent whenever the tablet tool comes in contact with the surface of the
++ tablet.
++
++ If the tool is already in contact with the tablet when entering the
++ input region, the client owning said region will receive a
++ wp_tablet.proximity_in event, followed by a wp_tablet.down
++ event and a wp_tablet.frame event.
++
++ Note that this event describes logical contact, not physical
++ contact. On some devices, a compositor may not consider a tool in
++ logical contact until a minimum physical pressure threshold is
++ exceeded.
++ </description>
++ <arg name="serial" type="uint"/>
++ </event>
++
++ <event name="up">
++ <description summary="tablet tool is no longer making contact">
++ Sent whenever the tablet tool stops making contact with the surface of
++ the tablet, or when the tablet tool moves out of the input region
++ and the compositor grab (if any) is dismissed.
++
++ If the tablet tool moves out of the input region while in contact
++ with the surface of the tablet and the compositor does not have an
++ ongoing grab on the surface, the client owning said region will
++ receive a wp_tablet.up event, followed by a wp_tablet.proximity_out
++ event and a wp_tablet.frame event. If the compositor has an ongoing
++ grab on this device, this event sequence is sent whenever the grab
++ is dismissed in the future.
++
++ Note that this event describes logical contact, not physical
++ contact. On some devices, a compositor may not consider a tool out
++ of logical contact until physical pressure falls below a specific
++ threshold.
++ </description>
++ </event>
++
++ <event name="motion">
++ <description summary="motion event">
++ Sent whenever a tablet tool moves.
++ </description>
++ <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++ <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++ </event>
++
++ <event name="pressure">
++ <description summary="pressure change event">
++ Sent whenever the pressure axis on a tool changes. The value of this
++ event is normalized to a value between 0 and 65535.
++
++ Note that pressure may be nonzero even when a tool is not in logical
++ contact. See the down and up events for more details.
++ </description>
++ <arg name="pressure" type="uint" summary="The current pressure value"/>
++ </event>
++
++ <event name="distance">
++ <description summary="distance change event">
++ Sent whenever the distance axis on a tool changes. The value of this
++ event is normalized to a value between 0 and 65535.
++
++ Note that distance may be nonzero even when a tool is not in logical
++ contact. See the down and up events for more details.
++ </description>
++ <arg name="distance" type="uint" summary="The current distance value"/>
++ </event>
++
++ <event name="tilt">
++ <description summary="tilt change event">
++ Sent whenever one or both of the tilt axes on a tool change. Each tilt
++ value is in 0.01 of a degree, relative to the z-axis of the tablet.
++ The angle is positive when the top of a tool tilts along the
++ positive x or y axis.
++ </description>
++ <arg name="tilt_x" type="int" summary="The current value of the X tilt axis"/>
++ <arg name="tilt_y" type="int" summary="The current value of the Y tilt axis"/>
++ </event>
++
++ <event name="rotation">
++ <description summary="z-rotation change event">
++ Sent whenever the z-rotation axis on the tool changes. The
++ rotation value is in 0.01 of a degree clockwise from the tool's
++ logical neutral position.
++ </description>
++ <arg name="degrees" type="int" summary="The current rotation of the Z axis"/>
++ </event>
++
++ <event name="slider">
++ <description summary="Slider position change event">
++ Sent whenever the slider position on the tool changes. The
++ value is normalized between -65535 and 65535, with 0 as the logical
++ neutral position of the slider.
++
++ The slider is available on e.g. the Wacom Airbrush tool.
++ </description>
++ <arg name="position" type="int" summary="The current position of slider"/>
++ </event>
++
++ <event name="wheel">
++ <description summary="Wheel delta event">
++ Sent whenever the wheel on the tool emits an event. This event
++ contains two values for the same axis change. The degrees value is
++ in 0.01 of a degree in the same orientation as the
++ wl_pointer.vertical_scroll axis. The clicks value is in discrete
++ logical clicks of the mouse wheel. This value may be zero if the
++ movement of the wheel was less than one logical click.
++
++ Clients should choose either value and avoid mixing degrees and
++ clicks. The compositor may accumulate values smaller than a logical
++ click and emulate click events when a certain threshold is met.
++ Thus, wl_tablet_tool.wheel events with non-zero clicks values may
++ have different degrees values.
++ </description>
++ <arg name="degrees" type="int" summary="The wheel delta in 0.01 of a degree"/>
++ <arg name="clicks" type="int" summary="The wheel delta in discrete clicks"/>
++ </event>
++
++ <enum name="button_state">
++ <description summary="physical button state">
++ Describes the physical state of a button that produced the button event.
++ </description>
++ <entry name="released" value="0" summary="button is not pressed"/>
++ <entry name="pressed" value="1" summary="button is pressed"/>
++ </enum>
++
++ <event name="button">
++ <description summary="button event">
++ Sent whenever a button on the tool is pressed or released.
++
++ If a button is held down when the tool moves in or out of proximity,
++ button events are generated by the compositor. See
++ wp_tablet_tool.proximity_in and wp_tablet_tool.proximity_out for
++ details.
++ </description>
++ <arg name="serial" type="uint"/>
++ <arg name="button" type="uint" summary="The button whose state has changed"/>
++ <arg name="state" type="uint" enum="button_state" summary="Whether the button was pressed or released"/>
++ </event>
++
++ <event name="frame">
++ <description summary="frame event">
++ Marks the end of a series of axis and/or button updates from the
++ tablet. The Wayland protocol requires axis updates to be sent
++ sequentially, however all events within a frame should be considered
++ one hardware event.
++ </description>
++ <arg name="time" type="uint" summary="The time of the event with millisecond granularity"/>
++ </event>
++
++ <enum name="error">
++ <entry name="role" value="0" summary="given wl_surface has another role"/>
++ </enum>
++ </interface>
++
++ <interface name="zwp_tablet_v1" version="1">
++ <description summary="graphics tablet device">
++ The wp_tablet interface represents one graphics tablet device. The
++ tablet interface itself does not generate events; all events are
++ generated by wp_tablet_tool objects when in proximity above a tablet.
++
++ A tablet has a number of static characteristics, e.g. device name and
++ pid/vid. These capabilities are sent in an event sequence after the
++ wp_tablet_seat.tablet_added event. This initial event sequence is
++ terminated by a wp_tablet.done event.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the tablet object">
++ This destroys the client's resource for this tablet object.
++ </description>
++ </request>
++
++ <event name="name">
++ <description summary="tablet device name">
++ This event is sent in the initial burst of events before the
++ wp_tablet.done event.
++ </description>
++ <arg name="name" type="string" summary="the device name"/>
++ </event>
++
++ <event name="id">
++ <description summary="tablet device USB vendor/product id">
++ This event is sent in the initial burst of events before the
++ wp_tablet.done event.
++ </description>
++ <arg name="vid" type="uint" summary="USB vendor id"/>
++ <arg name="pid" type="uint" summary="USB product id"/>
++ </event>
++
++ <event name="path">
++ <description summary="path to the device">
++ A system-specific device path that indicates which device is behind
++ this wp_tablet. This information may be used to gather additional
++ information about the device, e.g. through libwacom.
++
++ A device may have more than one device path. If so, multiple
++ wp_tablet.path events are sent. A device may be emulated and not
++ have a device path, and in that case this event will not be sent.
++
++ The format of the path is unspecified, it may be a device node, a
++ sysfs path, or some other identifier. It is up to the client to
++ identify the string provided.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet.done event.
++ </description>
++ <arg name="path" type="string" summary="path to local device"/>
++ </event>
++
++ <event name="done">
++ <description summary="tablet description events sequence complete">
++ This event is sent immediately to signal the end of the initial
++ burst of descriptive events. A client may consider the static
++ description of the tablet to be complete and finalize initialization
++ of the tablet.
++ </description>
++ </event>
++
++ <event name="removed">
++ <description summary="tablet removed event">
++ Sent when the tablet has been removed from the system. When a tablet
++ is removed, some tools may be removed.
++
++ When this event is received, the client must wp_tablet.destroy
++ the object.
++ </description>
++ </event>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="tablet_unstable_v2">
++
++ <copyright>
++ Copyright 2014 © Stephen "Lyude" Chandler Paul
++ Copyright 2015-2016 © Red Hat, Inc.
++
++ Permission is hereby granted, free of charge, to any person
++ obtaining a copy of this software and associated documentation files
++ (the "Software"), to deal in the Software without restriction,
++ including without limitation the rights to use, copy, modify, merge,
++ publish, distribute, sublicense, and/or sell copies of the Software,
++ and to permit persons to whom the Software is furnished to do so,
++ subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the
++ next paragraph) shall be included in all copies or substantial
++ portions of the Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ SOFTWARE.
++ </copyright>
++
++ <description summary="Wayland protocol for graphics tablets">
++ This description provides a high-level overview of the interplay between
++ the interfaces defined this protocol. For details, see the protocol
++ specification.
++
++ More than one tablet may exist, and device-specifics matter. Tablets are
++ not represented by a single virtual device like wl_pointer. A client
++ binds to the tablet manager object which is just a proxy object. From
++ that, the client requests wp_tablet_manager.get_tablet_seat(wl_seat)
++ and that returns the actual interface that has all the tablets. With
++ this indirection, we can avoid merging wp_tablet into the actual Wayland
++ protocol, a long-term benefit.
++
++ The wp_tablet_seat sends a "tablet added" event for each tablet
++ connected. That event is followed by descriptive events about the
++ hardware; currently that includes events for name, vid/pid and
++ a wp_tablet.path event that describes a local path. This path can be
++ used to uniquely identify a tablet or get more information through
++ libwacom. Emulated or nested tablets can skip any of those, e.g. a
++ virtual tablet may not have a vid/pid. The sequence of descriptive
++ events is terminated by a wp_tablet.done event to signal that a client
++ may now finalize any initialization for that tablet.
++
++ Events from tablets require a tool in proximity. Tools are also managed
++ by the tablet seat; a "tool added" event is sent whenever a tool is new
++ to the compositor. That event is followed by a number of descriptive
++ events about the hardware; currently that includes capabilities,
++ hardware id and serial number, and tool type. Similar to the tablet
++ interface, a wp_tablet_tool.done event is sent to terminate that initial
++ sequence.
++
++ Any event from a tool happens on the wp_tablet_tool interface. When the
++ tool gets into proximity of the tablet, a proximity_in event is sent on
++ the wp_tablet_tool interface, listing the tablet and the surface. That
++ event is followed by a motion event with the coordinates. After that,
++ it's the usual motion, axis, button, etc. events. The protocol's
++ serialisation means events are grouped by wp_tablet_tool.frame events.
++
++ Two special events (that don't exist in X) are down and up. They signal
++ "tip touching the surface". For tablets without real proximity
++ detection, the sequence is: proximity_in, motion, down, frame.
++
++ When the tool leaves proximity, a proximity_out event is sent. If any
++ button is still down, a button release event is sent before this
++ proximity event. These button events are sent in the same frame as the
++ proximity event to signal to the client that the buttons were held when
++ the tool left proximity.
++
++ If the tool moves out of the surface but stays in proximity (i.e.
++ between windows), compositor-specific grab policies apply. This usually
++ means that the proximity-out is delayed until all buttons are released.
++
++ Moving a tool physically from one tablet to the other has no real effect
++ on the protocol, since we already have the tool object from the "tool
++ added" event. All the information is already there and the proximity
++ events on both tablets are all a client needs to reconstruct what
++ happened.
++
++ Some extra axes are normalized, i.e. the client knows the range as
++ specified in the protocol (e.g. [0, 65535]), the granularity however is
++ unknown. The current normalized axes are pressure, distance, and slider.
++
++ Other extra axes are in physical units as specified in the protocol.
++ The current extra axes with physical units are tilt, rotation and
++ wheel rotation.
++
++ Since tablets work independently of the pointer controlled by the mouse,
++ the focus handling is independent too and controlled by proximity.
++ The wp_tablet_tool.set_cursor request sets a tool-specific cursor.
++ This cursor surface may be the same as the mouse cursor, and it may be
++ the same across tools but it is possible to be more fine-grained. For
++ example, a client may set different cursors for the pen and eraser.
++
++ Tools are generally independent of tablets and it is
++ compositor-specific policy when a tool can be removed. Common approaches
++ will likely include some form of removing a tool when all tablets the
++ tool was used on are removed.
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible changes
++ may be added together with the corresponding interface version bump.
++ Backward incompatible changes are done by bumping the version number in
++ the protocol and interface names and resetting the interface version.
++ Once the protocol is to be declared stable, the 'z' prefix and the
++ version number in the protocol and interface names are removed and the
++ interface version number is reset.
++ </description>
++
++ <interface name="zwp_tablet_manager_v2" version="1">
++ <description summary="controller object for graphic tablet devices">
++ An object that provides access to the graphics tablets available on this
++ system. All tablets are associated with a seat, to get access to the
++ actual tablets, use wp_tablet_manager.get_tablet_seat.
++ </description>
++
++ <request name="get_tablet_seat">
++ <description summary="get the tablet seat">
++ Get the wp_tablet_seat object for the given seat. This object
++ provides access to all graphics tablets in this seat.
++ </description>
++ <arg name="tablet_seat" type="new_id" interface="zwp_tablet_seat_v2"/>
++ <arg name="seat" type="object" interface="wl_seat" summary="The wl_seat object to retrieve the tablets for" />
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="release the memory for the tablet manager object">
++ Destroy the wp_tablet_manager object. Objects created from this
++ object are unaffected and should be destroyed separately.
++ </description>
++ </request>
++ </interface>
++
++ <interface name="zwp_tablet_seat_v2" version="1">
++ <description summary="controller object for graphic tablet devices of a seat">
++ An object that provides access to the graphics tablets available on this
++ seat. After binding to this interface, the compositor sends a set of
++ wp_tablet_seat.tablet_added and wp_tablet_seat.tool_added events.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="release the memory for the tablet seat object">
++ Destroy the wp_tablet_seat object. Objects created from this
++ object are unaffected and should be destroyed separately.
++ </description>
++ </request>
++
++ <event name="tablet_added">
++ <description summary="new device notification">
++ This event is sent whenever a new tablet becomes available on this
++ seat. This event only provides the object id of the tablet, any
++ static information about the tablet (device name, vid/pid, etc.) is
++ sent through the wp_tablet interface.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_tablet_v2" summary="the newly added graphics tablet"/>
++ </event>
++
++ <event name="tool_added">
++ <description summary="a new tool has been used with a tablet">
++ This event is sent whenever a tool that has not previously been used
++ with a tablet comes into use. This event only provides the object id
++ of the tool; any static information about the tool (capabilities,
++ type, etc.) is sent through the wp_tablet_tool interface.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_tablet_tool_v2" summary="the newly added tablet tool"/>
++ </event>
++
++ <event name="pad_added">
++ <description summary="new pad notification">
++ This event is sent whenever a new pad is known to the system. Typically,
++ pads are physically attached to tablets and a pad_added event is
++ sent immediately after the wp_tablet_seat.tablet_added.
++ However, some standalone pad devices logically attach to tablets at
++ runtime, and the client must wait for wp_tablet_pad.enter to know
++ the tablet a pad is attached to.
++
++ This event only provides the object id of the pad. All further
++ features (buttons, strips, rings) are sent through the wp_tablet_pad
++ interface.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_tablet_pad_v2" summary="the newly added pad"/>
++ </event>
++ </interface>
++
++ <interface name="zwp_tablet_tool_v2" version="1">
++ <description summary="a physical tablet tool">
++ An object that represents a physical tool that has been, or is
++ currently in use with a tablet in this seat. Each wp_tablet_tool
++ object stays valid until the client destroys it; the compositor
++ reuses the wp_tablet_tool object to indicate that the object's
++ respective physical tool has come into proximity of a tablet again.
++
++ A wp_tablet_tool object's relation to a physical tool depends on the
++ tablet's ability to report serial numbers. If the tablet supports
++ this capability, then the object represents a specific physical tool
++ and can be identified even when used on multiple tablets.
++
++ A tablet tool has a number of static characteristics, e.g. tool type,
++ hardware_serial and capabilities. These capabilities are sent in an
++ event sequence after the wp_tablet_seat.tool_added event before any
++ actual events from this tool. This initial event sequence is
++ terminated by a wp_tablet_tool.done event.
++
++ Tablet tool events are grouped by wp_tablet_tool.frame events.
++ Any events received before a wp_tablet_tool.frame event should be
++ considered part of the same hardware state change.
++ </description>
++
++ <request name="set_cursor">
++ <description summary="set the tablet tool's surface">
++ Sets the surface of the cursor used for this tool on the given
++ tablet. This request only takes effect if the tool is in proximity
++ of one of the requesting client's surfaces or the surface parameter
++ is the current pointer surface. If there was a previous surface set
++ with this request it is replaced. If surface is NULL, the cursor
++ image is hidden.
++
++ The parameters hotspot_x and hotspot_y define the position of the
++ pointer surface relative to the pointer location. Its top-left corner
++ is always at (x, y) - (hotspot_x, hotspot_y), where (x, y) are the
++ coordinates of the pointer location, in surface-local coordinates.
++
++ On surface.attach requests to the pointer surface, hotspot_x and
++ hotspot_y are decremented by the x and y parameters passed to the
++ request. Attach must be confirmed by wl_surface.commit as usual.
++
++ The hotspot can also be updated by passing the currently set pointer
++ surface to this request with new values for hotspot_x and hotspot_y.
++
++ The current and pending input regions of the wl_surface are cleared,
++ and wl_surface.set_input_region is ignored until the wl_surface is no
++ longer used as the cursor. When the use as a cursor ends, the current
++ and pending input regions become undefined, and the wl_surface is
++ unmapped.
++
++ This request gives the surface the role of a wp_tablet_tool cursor. A
++ surface may only ever be used as the cursor surface for one
++ wp_tablet_tool. If the surface already has another role or has
++ previously been used as cursor surface for a different tool, a
++ protocol error is raised.
++ </description>
++ <arg name="serial" type="uint" summary="serial of the enter event"/>
++ <arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
++ <arg name="hotspot_x" type="int" summary="surface-local x coordinate"/>
++ <arg name="hotspot_y" type="int" summary="surface-local y coordinate"/>
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the tool object">
++ This destroys the client's resource for this tool object.
++ </description>
++ </request>
++
++ <enum name="type">
++ <description summary="a physical tool type">
++ Describes the physical type of a tool. The physical type of a tool
++ generally defines its base usage.
++
++ The mouse tool represents a mouse-shaped tool that is not a relative
++ device but bound to the tablet's surface, providing absolute
++ coordinates.
++
++ The lens tool is a mouse-shaped tool with an attached lens to
++ provide precision focus.
++ </description>
++ <entry name="pen" value="0x140" summary="Pen"/>
++ <entry name="eraser" value="0x141" summary="Eraser"/>
++ <entry name="brush" value="0x142" summary="Brush"/>
++ <entry name="pencil" value="0x143" summary="Pencil"/>
++ <entry name="airbrush" value="0x144" summary="Airbrush"/>
++ <entry name="finger" value="0x145" summary="Finger"/>
++ <entry name="mouse" value="0x146" summary="Mouse"/>
++ <entry name="lens" value="0x147" summary="Lens"/>
++ </enum>
++
++ <event name="type">
++ <description summary="tool type">
++ The tool type is the high-level type of the tool and usually decides
++ the interaction expected from this tool.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet_tool.done event.
++ </description>
++ <arg name="tool_type" type="uint" enum="type" summary="the physical tool type"/>
++ </event>
++
++ <event name="hardware_serial">
++ <description summary="unique hardware serial number of the tool">
++ If the physical tool can be identified by a unique 64-bit serial
++ number, this event notifies the client of this serial number.
++
++ If multiple tablets are available in the same seat and the tool is
++ uniquely identifiable by the serial number, that tool may move
++ between tablets.
++
++ Otherwise, if the tool has no serial number and this event is
++ missing, the tool is tied to the tablet it first comes into
++ proximity with. Even if the physical tool is used on multiple
++ tablets, separate wp_tablet_tool objects will be created, one per
++ tablet.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet_tool.done event.
++ </description>
++ <arg name="hardware_serial_hi" type="uint" summary="the unique serial number of the tool, most significant bits"/>
++ <arg name="hardware_serial_lo" type="uint" summary="the unique serial number of the tool, least significant bits"/>
++ </event>
++
++ <event name="hardware_id_wacom">
++ <description summary="hardware id notification in Wacom's format">
++ This event notifies the client of a hardware id available on this tool.
++
++ The hardware id is a device-specific 64-bit id that provides extra
++ information about the tool in use, beyond the wl_tool.type
++ enumeration. The format of the id is specific to tablets made by
++ Wacom Inc. For example, the hardware id of a Wacom Grip
++ Pen (a stylus) is 0x802.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet_tool.done event.
++ </description>
++ <arg name="hardware_id_hi" type="uint" summary="the hardware id, most significant bits"/>
++ <arg name="hardware_id_lo" type="uint" summary="the hardware id, least significant bits"/>
++ </event>
++
++ <enum name="capability">
++ <description summary="capability flags for a tool">
++ Describes extra capabilities on a tablet.
++
++ Any tool must provide x and y values, extra axes are
++ device-specific.
++ </description>
++ <entry name="tilt" value="1" summary="Tilt axes"/>
++ <entry name="pressure" value="2" summary="Pressure axis"/>
++ <entry name="distance" value="3" summary="Distance axis"/>
++ <entry name="rotation" value="4" summary="Z-rotation axis"/>
++ <entry name="slider" value="5" summary="Slider axis"/>
++ <entry name="wheel" value="6" summary="Wheel axis"/>
++ </enum>
++
++ <event name="capability">
++ <description summary="tool capability notification">
++ This event notifies the client of any capabilities of this tool,
++ beyond the main set of x/y axes and tip up/down detection.
++
++ One event is sent for each extra capability available on this tool.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet_tool.done event.
++ </description>
++ <arg name="capability" type="uint" enum="capability" summary="the capability"/>
++ </event>
++
++ <event name="done">
++ <description summary="tool description events sequence complete">
++ This event signals the end of the initial burst of descriptive
++ events. A client may consider the static description of the tool to
++ be complete and finalize initialization of the tool.
++ </description>
++ </event>
++
++ <event name="removed">
++ <description summary="tool removed">
++ This event is sent when the tool is removed from the system and will
++ send no further events. Should the physical tool come back into
++ proximity later, a new wp_tablet_tool object will be created.
++
++ It is compositor-dependent when a tool is removed. A compositor may
++ remove a tool on proximity out, tablet removal or any other reason.
++ A compositor may also keep a tool alive until shutdown.
++
++ If the tool is currently in proximity, a proximity_out event will be
++ sent before the removed event. See wp_tablet_tool.proximity_out for
++ the handling of any buttons logically down.
++
++ When this event is received, the client must wp_tablet_tool.destroy
++ the object.
++ </description>
++ </event>
++
++ <event name="proximity_in">
++ <description summary="proximity in event">
++ Notification that this tool is focused on a certain surface.
++
++ This event can be received when the tool has moved from one surface to
++ another, or when the tool has come back into proximity above the
++ surface.
++
++ If any button is logically down when the tool comes into proximity,
++ the respective button event is sent after the proximity_in event but
++ within the same frame as the proximity_in event.
++ </description>
++ <arg name="serial" type="uint"/>
++ <arg name="tablet" type="object" interface="zwp_tablet_v2" summary="The tablet the tool is in proximity of"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="The current surface the tablet tool is over"/>
++ </event>
++
++ <event name="proximity_out">
++ <description summary="proximity out event">
++ Notification that this tool has either left proximity, or is no
++ longer focused on a certain surface.
++
++ When the tablet tool leaves proximity of the tablet, button release
++ events are sent for each button that was held down at the time of
++ leaving proximity. These events are sent before the proximity_out
++ event but within the same wp_tablet.frame.
++
++ If the tool stays within proximity of the tablet, but the focus
++ changes from one surface to another, a button release event may not
++ be sent until the button is actually released or the tool leaves the
++ proximity of the tablet.
++ </description>
++ </event>
++
++ <event name="down">
++ <description summary="tablet tool is making contact">
++ Sent whenever the tablet tool comes in contact with the surface of the
++ tablet.
++
++ If the tool is already in contact with the tablet when entering the
++ input region, the client owning said region will receive a
++ wp_tablet.proximity_in event, followed by a wp_tablet.down
++ event and a wp_tablet.frame event.
++
++ Note that this event describes logical contact, not physical
++ contact. On some devices, a compositor may not consider a tool in
++ logical contact until a minimum physical pressure threshold is
++ exceeded.
++ </description>
++ <arg name="serial" type="uint"/>
++ </event>
++
++ <event name="up">
++ <description summary="tablet tool is no longer making contact">
++ Sent whenever the tablet tool stops making contact with the surface of
++ the tablet, or when the tablet tool moves out of the input region
++ and the compositor grab (if any) is dismissed.
++
++ If the tablet tool moves out of the input region while in contact
++ with the surface of the tablet and the compositor does not have an
++ ongoing grab on the surface, the client owning said region will
++ receive a wp_tablet.up event, followed by a wp_tablet.proximity_out
++ event and a wp_tablet.frame event. If the compositor has an ongoing
++ grab on this device, this event sequence is sent whenever the grab
++ is dismissed in the future.
++
++ Note that this event describes logical contact, not physical
++ contact. On some devices, a compositor may not consider a tool out
++ of logical contact until physical pressure falls below a specific
++ threshold.
++ </description>
++ </event>
++
++ <event name="motion">
++ <description summary="motion event">
++ Sent whenever a tablet tool moves.
++ </description>
++ <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++ <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++ </event>
++
++ <event name="pressure">
++ <description summary="pressure change event">
++ Sent whenever the pressure axis on a tool changes. The value of this
++ event is normalized to a value between 0 and 65535.
++
++ Note that pressure may be nonzero even when a tool is not in logical
++ contact. See the down and up events for more details.
++ </description>
++ <arg name="pressure" type="uint" summary="The current pressure value"/>
++ </event>
++
++ <event name="distance">
++ <description summary="distance change event">
++ Sent whenever the distance axis on a tool changes. The value of this
++ event is normalized to a value between 0 and 65535.
++
++ Note that distance may be nonzero even when a tool is not in logical
++ contact. See the down and up events for more details.
++ </description>
++ <arg name="distance" type="uint" summary="The current distance value"/>
++ </event>
++
++ <event name="tilt">
++ <description summary="tilt change event">
++ Sent whenever one or both of the tilt axes on a tool change. Each tilt
++ value is in degrees, relative to the z-axis of the tablet.
++ The angle is positive when the top of a tool tilts along the
++ positive x or y axis.
++ </description>
++ <arg name="tilt_x" type="fixed" summary="The current value of the X tilt axis"/>
++ <arg name="tilt_y" type="fixed" summary="The current value of the Y tilt axis"/>
++ </event>
++
++ <event name="rotation">
++ <description summary="z-rotation change event">
++ Sent whenever the z-rotation axis on the tool changes. The
++ rotation value is in degrees clockwise from the tool's
++ logical neutral position.
++ </description>
++ <arg name="degrees" type="fixed" summary="The current rotation of the Z axis"/>
++ </event>
++
++ <event name="slider">
++ <description summary="Slider position change event">
++ Sent whenever the slider position on the tool changes. The
++ value is normalized between -65535 and 65535, with 0 as the logical
++ neutral position of the slider.
++
++ The slider is available on e.g. the Wacom Airbrush tool.
++ </description>
++ <arg name="position" type="int" summary="The current position of slider"/>
++ </event>
++
++ <event name="wheel">
++ <description summary="Wheel delta event">
++ Sent whenever the wheel on the tool emits an event. This event
++ contains two values for the same axis change. The degrees value is
++ in the same orientation as the wl_pointer.vertical_scroll axis. The
++ clicks value is in discrete logical clicks of the mouse wheel. This
++ value may be zero if the movement of the wheel was less
++ than one logical click.
++
++ Clients should choose either value and avoid mixing degrees and
++ clicks. The compositor may accumulate values smaller than a logical
++ click and emulate click events when a certain threshold is met.
++ Thus, wl_tablet_tool.wheel events with non-zero clicks values may
++ have different degrees values.
++ </description>
++ <arg name="degrees" type="fixed" summary="The wheel delta in degrees"/>
++ <arg name="clicks" type="int" summary="The wheel delta in discrete clicks"/>
++ </event>
++
++ <enum name="button_state">
++ <description summary="physical button state">
++ Describes the physical state of a button that produced the button event.
++ </description>
++ <entry name="released" value="0" summary="button is not pressed"/>
++ <entry name="pressed" value="1" summary="button is pressed"/>
++ </enum>
++
++ <event name="button">
++ <description summary="button event">
++ Sent whenever a button on the tool is pressed or released.
++
++ If a button is held down when the tool moves in or out of proximity,
++ button events are generated by the compositor. See
++ wp_tablet_tool.proximity_in and wp_tablet_tool.proximity_out for
++ details.
++ </description>
++ <arg name="serial" type="uint"/>
++ <arg name="button" type="uint" summary="The button whose state has changed"/>
++ <arg name="state" type="uint" enum="button_state" summary="Whether the button was pressed or released"/>
++ </event>
++
++ <event name="frame">
++ <description summary="frame event">
++ Marks the end of a series of axis and/or button updates from the
++ tablet. The Wayland protocol requires axis updates to be sent
++ sequentially, however all events within a frame should be considered
++ one hardware event.
++ </description>
++ <arg name="time" type="uint" summary="The time of the event with millisecond granularity"/>
++ </event>
++
++ <enum name="error">
++ <entry name="role" value="0" summary="given wl_surface has another role"/>
++ </enum>
++ </interface>
++
++ <interface name="zwp_tablet_v2" version="1">
++ <description summary="graphics tablet device">
++ The wp_tablet interface represents one graphics tablet device. The
++ tablet interface itself does not generate events; all events are
++ generated by wp_tablet_tool objects when in proximity above a tablet.
++
++ A tablet has a number of static characteristics, e.g. device name and
++ pid/vid. These capabilities are sent in an event sequence after the
++ wp_tablet_seat.tablet_added event. This initial event sequence is
++ terminated by a wp_tablet.done event.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the tablet object">
++ This destroys the client's resource for this tablet object.
++ </description>
++ </request>
++
++ <event name="name">
++ <description summary="tablet device name">
++ This event is sent in the initial burst of events before the
++ wp_tablet.done event.
++ </description>
++ <arg name="name" type="string" summary="the device name"/>
++ </event>
++
++ <event name="id">
++ <description summary="tablet device USB vendor/product id">
++ This event is sent in the initial burst of events before the
++ wp_tablet.done event.
++ </description>
++ <arg name="vid" type="uint" summary="USB vendor id"/>
++ <arg name="pid" type="uint" summary="USB product id"/>
++ </event>
++
++ <event name="path">
++ <description summary="path to the device">
++ A system-specific device path that indicates which device is behind
++ this wp_tablet. This information may be used to gather additional
++ information about the device, e.g. through libwacom.
++
++ A device may have more than one device path. If so, multiple
++ wp_tablet.path events are sent. A device may be emulated and not
++ have a device path, and in that case this event will not be sent.
++
++ The format of the path is unspecified, it may be a device node, a
++ sysfs path, or some other identifier. It is up to the client to
++ identify the string provided.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet.done event.
++ </description>
++ <arg name="path" type="string" summary="path to local device"/>
++ </event>
++
++ <event name="done">
++ <description summary="tablet description events sequence complete">
++ This event is sent immediately to signal the end of the initial
++ burst of descriptive events. A client may consider the static
++ description of the tablet to be complete and finalize initialization
++ of the tablet.
++ </description>
++ </event>
++
++ <event name="removed">
++ <description summary="tablet removed event">
++ Sent when the tablet has been removed from the system. When a tablet
++ is removed, some tools may be removed.
++
++ When this event is received, the client must wp_tablet.destroy
++ the object.
++ </description>
++ </event>
++ </interface>
++
++ <interface name="zwp_tablet_pad_ring_v2" version="1">
++ <description summary="pad ring">
++ A circular interaction area, such as the touch ring on the Wacom Intuos
++ Pro series tablets.
++
++ Events on a ring are logically grouped by the wl_tablet_pad_ring.frame
++ event.
++ </description>
++
++ <request name="set_feedback">
++ <description summary="set compositor feedback">
++ Request that the compositor use the provided feedback string
++ associated with this ring. This request should be issued immediately
++ after a wp_tablet_pad_group.mode_switch event from the corresponding
++ group is received, or whenever the ring is mapped to a different
++ action. See wp_tablet_pad_group.mode_switch for more details.
++
++ Clients are encouraged to provide context-aware descriptions for
++ the actions associated with the ring; compositors may use this
++ information to offer visual feedback about the button layout
++ (eg. on-screen displays).
++
++ The provided string 'description' is a UTF-8 encoded string to be
++ associated with this ring, and is considered user-visible; general
++ internationalization rules apply.
++
++ The serial argument will be that of the last
++ wp_tablet_pad_group.mode_switch event received for the group of this
++ ring. Requests providing other serials than the most recent one will be
++ ignored.
++ </description>
++ <arg name="description" type="string" summary="ring description"/>
++ <arg name="serial" type="uint" summary="serial of the mode switch event"/>
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the ring object">
++ This destroys the client's resource for this ring object.
++ </description>
++ </request>
++
++ <enum name="source">
++ <description summary="ring axis source">
++ Describes the source types for ring events. This indicates to the
++ client how a ring event was physically generated; a client may
++ adjust the user interface accordingly. For example, events
++ from a "finger" source may trigger kinetic scrolling.
++ </description>
++ <entry name="finger" value="1" summary="finger"/>
++ </enum>
++
++ <event name="source">
++ <description summary="ring event source">
++ Source information for ring events.
++
++ This event does not occur on its own. It is sent before a
++ wp_tablet_pad_ring.frame event and carries the source information
++ for all events within that frame.
++
++ The source specifies how this event was generated. If the source is
++ wp_tablet_pad_ring.source.finger, a wp_tablet_pad_ring.stop event
++ will be sent when the user lifts the finger off the device.
++
++ This event is optional. If the source is unknown for an interaction,
++ no event is sent.
++ </description>
++ <arg name="source" type="uint" enum="source" summary="the event source"/>
++ </event>
++
++ <event name="angle">
++ <description summary="angle changed">
++ Sent whenever the angle on a ring changes.
++
++ The angle is provided in degrees clockwise from the logical
++ north of the ring in the pad's current rotation.
++ </description>
++ <arg name="degrees" type="fixed" summary="the current angle in degrees"/>
++ </event>
++
++ <event name="stop">
++ <description summary="interaction stopped">
++ Stop notification for ring events.
++
++ For some wp_tablet_pad_ring.source types, a wp_tablet_pad_ring.stop
++ event is sent to notify a client that the interaction with the ring
++ has terminated. This enables the client to implement kinetic scrolling.
++ See the wp_tablet_pad_ring.source documentation for information on
++ when this event may be generated.
++
++ Any wp_tablet_pad_ring.angle events with the same source after this
++ event should be considered as the start of a new interaction.
++ </description>
++ </event>
++
++ <event name="frame">
++ <description summary="end of a ring event sequence">
++ Indicates the end of a set of ring events that logically belong
++ together. A client is expected to accumulate the data in all events
++ within the frame before proceeding.
++
++ All wp_tablet_pad_ring events before a wp_tablet_pad_ring.frame event belong
++ logically together. For example, on termination of a finger interaction
++ on a ring the compositor will send a wp_tablet_pad_ring.source event,
++ a wp_tablet_pad_ring.stop event and a wp_tablet_pad_ring.frame event.
++
++ A wp_tablet_pad_ring.frame event is sent for every logical event
++ group, even if the group only contains a single wp_tablet_pad_ring
++ event. Specifically, a client may get a sequence: angle, frame,
++ angle, frame, etc.
++ </description>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ </event>
++ </interface>
++
++ <interface name="zwp_tablet_pad_strip_v2" version="1">
++ <description summary="pad strip">
++ A linear interaction area, such as the strips found in Wacom Cintiq
++ models.
++
++ Events on a strip are logically grouped by the wl_tablet_pad_strip.frame
++ event.
++ </description>
++
++ <request name="set_feedback">
++ <description summary="set compositor feedback">
++ Requests the compositor to use the provided feedback string
++ associated with this strip. This request should be issued immediately
++ after a wp_tablet_pad_group.mode_switch event from the corresponding
++ group is received, or whenever the strip is mapped to a different
++ action. See wp_tablet_pad_group.mode_switch for more details.
++
++ Clients are encouraged to provide context-aware descriptions for
++ the actions associated with the strip, and compositors may use this
++ information to offer visual feedback about the button layout
++ (eg. on-screen displays).
++
++ The provided string 'description' is a UTF-8 encoded string to be
++ associated with this ring, and is considered user-visible; general
++ internationalization rules apply.
++
++ The serial argument will be that of the last
++ wp_tablet_pad_group.mode_switch event received for the group of this
++ strip. Requests providing other serials than the most recent one will be
++ ignored.
++ </description>
++ <arg name="description" type="string" summary="strip description"/>
++ <arg name="serial" type="uint" summary="serial of the mode switch event"/>
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the strip object">
++ This destroys the client's resource for this strip object.
++ </description>
++ </request>
++
++ <enum name="source">
++ <description summary="strip axis source">
++ Describes the source types for strip events. This indicates to the
++ client how a strip event was physically generated; a client may
++ adjust the user interface accordingly. For example, events
++ from a "finger" source may trigger kinetic scrolling.
++ </description>
++ <entry name="finger" value="1" summary="finger"/>
++ </enum>
++
++ <event name="source">
++ <description summary="strip event source">
++ Source information for strip events.
++
++ This event does not occur on its own. It is sent before a
++ wp_tablet_pad_strip.frame event and carries the source information
++ for all events within that frame.
++
++ The source specifies how this event was generated. If the source is
++ wp_tablet_pad_strip.source.finger, a wp_tablet_pad_strip.stop event
++ will be sent when the user lifts their finger off the device.
++
++ This event is optional. If the source is unknown for an interaction,
++ no event is sent.
++ </description>
++ <arg name="source" type="uint" enum="source" summary="the event source"/>
++ </event>
++
++ <event name="position">
++ <description summary="position changed">
++ Sent whenever the position on a strip changes.
++
++ The position is normalized to a range of [0, 65535], the 0-value
++ represents the top-most and/or left-most position of the strip in
++ the pad's current rotation.
++ </description>
++ <arg name="position" type="uint" summary="the current position"/>
++ </event>
++
++ <event name="stop">
++ <description summary="interaction stopped">
++ Stop notification for strip events.
++
++ For some wp_tablet_pad_strip.source types, a wp_tablet_pad_strip.stop
++ event is sent to notify a client that the interaction with the strip
++ has terminated. This enables the client to implement kinetic
++ scrolling. See the wp_tablet_pad_strip.source documentation for
++ information on when this event may be generated.
++
++ Any wp_tablet_pad_strip.position events with the same source after this
++ event should be considered as the start of a new interaction.
++ </description>
++ </event>
++
++ <event name="frame">
++ <description summary="end of a strip event sequence">
++ Indicates the end of a set of events that represent one logical
++ hardware strip event. A client is expected to accumulate the data
++ in all events within the frame before proceeding.
++
++ All wp_tablet_pad_strip events before a wp_tablet_pad_strip.frame event belong
++ logically together. For example, on termination of a finger interaction
++ on a strip the compositor will send a wp_tablet_pad_strip.source event,
++ a wp_tablet_pad_strip.stop event and a wp_tablet_pad_strip.frame
++ event.
++
++ A wp_tablet_pad_strip.frame event is sent for every logical event
++ group, even if the group only contains a single wp_tablet_pad_strip
++ event. Specifically, a client may get a sequence: position, frame,
++ position, frame, etc.
++ </description>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ </event>
++ </interface>
++
++ <interface name="zwp_tablet_pad_group_v2" version="1">
++ <description summary="a set of buttons, rings and strips">
++ A pad group describes a distinct (sub)set of buttons, rings and strips
++ present in the tablet. The criteria of this grouping is usually positional,
++ eg. if a tablet has buttons on the left and right side, 2 groups will be
++ presented. The physical arrangement of groups is undisclosed and may
++ change on the fly.
++
++ Pad groups will announce their features during pad initialization. Between
++ the corresponding wp_tablet_pad.group event and wp_tablet_pad_group.done, the
++ pad group will announce the buttons, rings and strips contained in it,
++ plus the number of supported modes.
++
++ Modes are a mechanism to allow multiple groups of actions for every element
++ in the pad group. The number of groups and available modes in each is
++ persistent across device plugs. The current mode is user-switchable, it
++ will be announced through the wp_tablet_pad_group.mode_switch event both
++ whenever it is switched, and after wp_tablet_pad.enter.
++
++ The current mode logically applies to all elements in the pad group,
++ although it is at clients' discretion whether to actually perform different
++ actions, and/or issue the respective .set_feedback requests to notify the
++ compositor. See the wp_tablet_pad_group.mode_switch event for more details.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the pad object">
++ Destroy the wp_tablet_pad_group object. Objects created from this object
++ are unaffected and should be destroyed separately.
++ </description>
++ </request>
++
++ <event name="buttons">
++ <description summary="buttons announced">
++ Sent on wp_tablet_pad_group initialization to announce the available
++ buttons in the group. Button indices start at 0, a button may only be
++ in one group at a time.
++
++ This event is first sent in the initial burst of events before the
++ wp_tablet_pad_group.done event.
++
++ Some buttons are reserved by the compositor. These buttons may not be
++ assigned to any wp_tablet_pad_group. Compositors may broadcast this
++ event in the case of changes to the mapping of these reserved buttons.
++ If the compositor happens to reserve all buttons in a group, this event
++ will be sent with an empty array.
++ </description>
++ <arg name="buttons" type="array" summary="buttons in this group"/>
++ </event>
++
++ <event name="ring">
++ <description summary="ring announced">
++ Sent on wp_tablet_pad_group initialization to announce available rings.
++ One event is sent for each ring available on this pad group.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet_pad_group.done event.
++ </description>
++ <arg name="ring" type="new_id" interface="zwp_tablet_pad_ring_v2"/>
++ </event>
++
++ <event name="strip">
++ <description summary="strip announced">
++ Sent on wp_tablet_pad initialization to announce available strips.
++ One event is sent for each strip available on this pad group.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet_pad_group.done event.
++ </description>
++ <arg name="strip" type="new_id" interface="zwp_tablet_pad_strip_v2"/>
++ </event>
++
++ <event name="modes">
++ <description summary="mode-switch ability announced">
++ Sent on wp_tablet_pad_group initialization to announce that the pad
++ group may switch between modes. A client may use a mode to store a
++ specific configuration for buttons, rings and strips and use the
++ wl_tablet_pad_group.mode_switch event to toggle between these
++ configurations. Mode indices start at 0.
++
++ Switching modes is compositor-dependent. See the
++ wp_tablet_pad_group.mode_switch event for more details.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet_pad_group.done event. This event is only sent when more than
++ more than one mode is available.
++ </description>
++ <arg name="modes" type="uint" summary="the number of modes"/>
++ </event>
++
++ <event name="done">
++ <description summary="tablet group description events sequence complete">
++ This event is sent immediately to signal the end of the initial
++ burst of descriptive events. A client may consider the static
++ description of the tablet to be complete and finalize initialization
++ of the tablet group.
++ </description>
++ </event>
++
++ <event name="mode_switch">
++ <description summary="mode switch event">
++ Notification that the mode was switched.
++
++ A mode applies to all buttons, rings and strips in a group
++ simultaneously, but a client is not required to assign different actions
++ for each mode. For example, a client may have mode-specific button
++ mappings but map the ring to vertical scrolling in all modes. Mode
++ indices start at 0.
++
++ Switching modes is compositor-dependent. The compositor may provide
++ visual cues to the client about the mode, e.g. by toggling LEDs on
++ the tablet device. Mode-switching may be software-controlled or
++ controlled by one or more physical buttons. For example, on a Wacom
++ Intuos Pro, the button inside the ring may be assigned to switch
++ between modes.
++
++ The compositor will also send this event after wp_tablet_pad.enter on
++ each group in order to notify of the current mode. Groups that only
++ feature one mode will use mode=0 when emitting this event.
++
++ If a button action in the new mode differs from the action in the
++ previous mode, the client should immediately issue a
++ wp_tablet_pad.set_feedback request for each changed button.
++
++ If a ring or strip action in the new mode differs from the action
++ in the previous mode, the client should immediately issue a
++ wp_tablet_ring.set_feedback or wp_tablet_strip.set_feedback request
++ for each changed ring or strip.
++ </description>
++ <arg name="time" type="uint" summary="the time of the event with millisecond granularity"/>
++ <arg name="serial" type="uint"/>
++ <arg name="mode" type="uint" summary="the new mode of the pad"/>
++ </event>
++ </interface>
++
++ <interface name="zwp_tablet_pad_v2" version="1">
++ <description summary="a set of buttons, rings and strips">
++ A pad device is a set of buttons, rings and strips
++ usually physically present on the tablet device itself. Some
++ exceptions exist where the pad device is physically detached, e.g. the
++ Wacom ExpressKey Remote.
++
++ Pad devices have no axes that control the cursor and are generally
++ auxiliary devices to the tool devices used on the tablet surface.
++
++ A pad device has a number of static characteristics, e.g. the number
++ of rings. These capabilities are sent in an event sequence after the
++ wp_tablet_seat.pad_added event before any actual events from this pad.
++ This initial event sequence is terminated by a wp_tablet_pad.done
++ event.
++
++ All pad features (buttons, rings and strips) are logically divided into
++ groups and all pads have at least one group. The available groups are
++ notified through the wp_tablet_pad.group event; the compositor will
++ emit one event per group before emitting wp_tablet_pad.done.
++
++ Groups may have multiple modes. Modes allow clients to map multiple
++ actions to a single pad feature. Only one mode can be active per group,
++ although different groups may have different active modes.
++ </description>
++
++ <request name="set_feedback">
++ <description summary="set compositor feedback">
++ Requests the compositor to use the provided feedback string
++ associated with this button. This request should be issued immediately
++ after a wp_tablet_pad_group.mode_switch event from the corresponding
++ group is received, or whenever a button is mapped to a different
++ action. See wp_tablet_pad_group.mode_switch for more details.
++
++ Clients are encouraged to provide context-aware descriptions for
++ the actions associated with each button, and compositors may use
++ this information to offer visual feedback on the button layout
++ (e.g. on-screen displays).
++
++ Button indices start at 0. Setting the feedback string on a button
++ that is reserved by the compositor (i.e. not belonging to any
++ wp_tablet_pad_group) does not generate an error but the compositor
++ is free to ignore the request.
++
++ The provided string 'description' is a UTF-8 encoded string to be
++ associated with this ring, and is considered user-visible; general
++ internationalization rules apply.
++
++ The serial argument will be that of the last
++ wp_tablet_pad_group.mode_switch event received for the group of this
++ button. Requests providing other serials than the most recent one will
++ be ignored.
++ </description>
++ <arg name="button" type="uint" summary="button index"/>
++ <arg name="description" type="string" summary="button description"/>
++ <arg name="serial" type="uint" summary="serial of the mode switch event"/>
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the pad object">
++ Destroy the wp_tablet_pad object. Objects created from this object
++ are unaffected and should be destroyed separately.
++ </description>
++ </request>
++
++ <event name="group">
++ <description summary="group announced">
++ Sent on wp_tablet_pad initialization to announce available groups.
++ One event is sent for each pad group available.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet_pad.done event. At least one group will be announced.
++ </description>
++ <arg name="pad_group" type="new_id" interface="zwp_tablet_pad_group_v2"/>
++ </event>
++
++ <event name="path">
++ <description summary="path to the device">
++ A system-specific device path that indicates which device is behind
++ this wp_tablet_pad. This information may be used to gather additional
++ information about the device, e.g. through libwacom.
++
++ The format of the path is unspecified, it may be a device node, a
++ sysfs path, or some other identifier. It is up to the client to
++ identify the string provided.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet_pad.done event.
++ </description>
++ <arg name="path" type="string" summary="path to local device"/>
++ </event>
++
++ <event name="buttons">
++ <description summary="buttons announced">
++ Sent on wp_tablet_pad initialization to announce the available
++ buttons.
++
++ This event is sent in the initial burst of events before the
++ wp_tablet_pad.done event. This event is only sent when at least one
++ button is available.
++ </description>
++ <arg name="buttons" type="uint" summary="the number of buttons"/>
++ </event>
++
++ <event name="done">
++ <description summary="pad description event sequence complete">
++ This event signals the end of the initial burst of descriptive
++ events. A client may consider the static description of the pad to
++ be complete and finalize initialization of the pad.
++ </description>
++ </event>
++
++ <enum name="button_state">
++ <description summary="physical button state">
++ Describes the physical state of a button that caused the button
++ event.
++ </description>
++ <entry name="released" value="0" summary="the button is not pressed"/>
++ <entry name="pressed" value="1" summary="the button is pressed"/>
++ </enum>
++
++ <event name="button">
++ <description summary="physical button state">
++ Sent whenever the physical state of a button changes.
++ </description>
++ <arg name="time" type="uint" summary="the time of the event with millisecond granularity"/>
++ <arg name="button" type="uint" summary="the index of the button that changed state"/>
++ <arg name="state" type="uint" enum="button_state"/>
++ </event>
++
++ <event name="enter">
++ <description summary="enter event">
++ Notification that this pad is focused on the specified surface.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the enter event"/>
++ <arg name="tablet" type="object" interface="zwp_tablet_v2" summary="the tablet the pad is attached to"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="surface the pad is focused on"/>
++ </event>
++
++ <event name="leave">
++ <description summary="leave event">
++ Notification that this pad is no longer focused on the specified
++ surface.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the leave event"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="surface the pad is no longer focused on"/>
++ </event>
++
++ <event name="removed">
++ <description summary="pad removed event">
++ Sent when the pad has been removed from the system. When a tablet
++ is removed its pad(s) will be removed too.
++
++ When this event is received, the client must destroy all rings, strips
++ and groups that were offered by this pad, and issue wp_tablet_pad.destroy
++ the pad itself.
++ </description>
++ </event>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++Text input protocol
++
++Maintainers:
++Jan Arne Petersen <janarne@gmail.com>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="text_input_unstable_v1">
++
++ <copyright>
++ Copyright © 2012, 2013 Intel Corporation
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="zwp_text_input_v1" version="1">
++ <description summary="text input">
++ An object used for text input. Adds support for text input and input
++ methods to applications. A text_input object is created from a
++ wl_text_input_manager and corresponds typically to a text entry in an
++ application.
++
++ Requests are used to activate/deactivate the text_input object and set
++ state information like surrounding and selected text or the content type.
++ The information about entered text is sent to the text_input object via
++ the pre-edit and commit events. Using this interface removes the need
++ for applications to directly process hardware key events and compose text
++ out of them.
++
++ Text is generally UTF-8 encoded, indices and lengths are in bytes.
++
++ Serials are used to synchronize the state between the text input and
++ an input method. New serials are sent by the text input in the
++ commit_state request and are used by the input method to indicate
++ the known text input state in events like preedit_string, commit_string,
++ and keysym. The text input can then ignore events from the input method
++ which are based on an outdated state (for example after a reset).
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible changes
++ may be added together with the corresponding interface version bump.
++ Backward incompatible changes are done by bumping the version number in
++ the protocol and interface names and resetting the interface version.
++ Once the protocol is to be declared stable, the 'z' prefix and the
++ version number in the protocol and interface names are removed and the
++ interface version number is reset.
++ </description>
++
++ <request name="activate">
++ <description summary="request activation">
++ Requests the text_input object to be activated (typically when the
++ text entry gets focus).
++
++ The seat argument is a wl_seat which maintains the focus for this
++ activation. The surface argument is a wl_surface assigned to the
++ text_input object and tracked for focus lost. The enter event
++ is emitted on successful activation.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat"/>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ </request>
++
++ <request name="deactivate">
++ <description summary="request deactivation">
++ Requests the text_input object to be deactivated (typically when the
++ text entry lost focus). The seat argument is a wl_seat which was used
++ for activation.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat"/>
++ </request>
++
++ <request name="show_input_panel">
++ <description summary="show input panels">
++ Requests input panels (virtual keyboard) to show.
++ </description>
++ </request>
++
++ <request name="hide_input_panel">
++ <description summary="hide input panels">
++ Requests input panels (virtual keyboard) to hide.
++ </description>
++ </request>
++
++ <request name="reset">
++ <description summary="reset">
++ Should be called by an editor widget when the input state should be
++ reset, for example after the text was changed outside of the normal
++ input method flow.
++ </description>
++ </request>
++
++ <request name="set_surrounding_text">
++ <description summary="sets the surrounding text">
++ Sets the plain surrounding text around the input position. Text is
++ UTF-8 encoded. Cursor is the byte offset within the
++ surrounding text. Anchor is the byte offset of the
++ selection anchor within the surrounding text. If there is no selected
++ text anchor, then it is the same as cursor.
++ </description>
++ <arg name="text" type="string"/>
++ <arg name="cursor" type="uint"/>
++ <arg name="anchor" type="uint"/>
++ </request>
++
++ <enum name="content_hint" bitfield="true">
++ <description summary="content hint">
++ Content hint is a bitmask to allow to modify the behavior of the text
++ input.
++ </description>
++ <entry name="none" value="0x0" summary="no special behaviour"/>
++ <entry name="default" value="0x7" summary="auto completion, correction and capitalization"/>
++ <entry name="password" value="0xc0" summary="hidden and sensitive text"/>
++ <entry name="auto_completion" value="0x1" summary="suggest word completions"/>
++ <entry name="auto_correction" value="0x2" summary="suggest word corrections"/>
++ <entry name="auto_capitalization" value="0x4" summary="switch to uppercase letters at the start of a sentence"/>
++ <entry name="lowercase" value="0x8" summary="prefer lowercase letters"/>
++ <entry name="uppercase" value="0x10" summary="prefer uppercase letters"/>
++ <entry name="titlecase" value="0x20" summary="prefer casing for titles and headings (can be language dependent)"/>
++ <entry name="hidden_text" value="0x40" summary="characters should be hidden"/>
++ <entry name="sensitive_data" value="0x80" summary="typed text should not be stored"/>
++ <entry name="latin" value="0x100" summary="just latin characters should be entered"/>
++ <entry name="multiline" value="0x200" summary="the text input is multiline"/>
++ </enum>
++
++ <enum name="content_purpose">
++ <description summary="content purpose">
++ The content purpose allows to specify the primary purpose of a text
++ input.
++
++ This allows an input method to show special purpose input panels with
++ extra characters or to disallow some characters.
++ </description>
++ <entry name="normal" value="0" summary="default input, allowing all characters"/>
++ <entry name="alpha" value="1" summary="allow only alphabetic characters"/>
++ <entry name="digits" value="2" summary="allow only digits"/>
++ <entry name="number" value="3" summary="input a number (including decimal separator and sign)"/>
++ <entry name="phone" value="4" summary="input a phone number"/>
++ <entry name="url" value="5" summary="input an URL"/>
++ <entry name="email" value="6" summary="input an email address"/>
++ <entry name="name" value="7" summary="input a name of a person"/>
++ <entry name="password" value="8" summary="input a password (combine with password or sensitive_data hint)"/>
++ <entry name="date" value="9" summary="input a date"/>
++ <entry name="time" value="10" summary="input a time"/>
++ <entry name="datetime" value="11" summary="input a date and time"/>
++ <entry name="terminal" value="12" summary="input for a terminal"/>
++ </enum>
++
++ <request name="set_content_type">
++ <description summary="set content purpose and hint">
++ Sets the content purpose and content hint. While the purpose is the
++ basic purpose of an input field, the hint flags allow to modify some
++ of the behavior.
++
++ When no content type is explicitly set, a normal content purpose with
++ default hints (auto completion, auto correction, auto capitalization)
++ should be assumed.
++ </description>
++ <arg name="hint" type="uint" enum="content_hint" />
++ <arg name="purpose" type="uint" enum="content_purpose" />
++ </request>
++
++ <request name="set_cursor_rectangle">
++ <arg name="x" type="int"/>
++ <arg name="y" type="int"/>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ </request>
++
++ <request name="set_preferred_language">
++ <description summary="sets preferred language">
++ Sets a specific language. This allows for example a virtual keyboard to
++ show a language specific layout. The "language" argument is an RFC-3066
++ format language tag.
++
++ It could be used for example in a word processor to indicate the
++ language of the currently edited document or in an instant message
++ application which tracks languages of contacts.
++ </description>
++ <arg name="language" type="string"/>
++ </request>
++
++ <request name="commit_state">
++ <arg name="serial" type="uint" summary="used to identify the known state"/>
++ </request>
++
++ <request name="invoke_action">
++ <arg name="button" type="uint"/>
++ <arg name="index" type="uint"/>
++ </request>
++
++ <event name="enter">
++ <description summary="enter event">
++ Notify the text_input object when it received focus. Typically in
++ response to an activate request.
++ </description>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ </event>
++
++ <event name="leave">
++ <description summary="leave event">
++ Notify the text_input object when it lost focus. Either in response
++ to a deactivate request or when the assigned surface lost focus or was
++ destroyed.
++ </description>
++ </event>
++
++ <event name="modifiers_map">
++ <description summary="modifiers map">
++ Transfer an array of 0-terminated modifier names. The position in
++ the array is the index of the modifier as used in the modifiers
++ bitmask in the keysym event.
++ </description>
++ <arg name="map" type="array"/>
++ </event>
++
++ <event name="input_panel_state">
++ <description summary="state of the input panel">
++ Notify when the visibility state of the input panel changed.
++ </description>
++ <arg name="state" type="uint"/>
++ </event>
++
++ <event name="preedit_string">
++ <description summary="pre-edit">
++ Notify when a new composing text (pre-edit) should be set around the
++ current cursor position. Any previously set composing text should
++ be removed.
++
++ The commit text can be used to replace the preedit text on reset
++ (for example on unfocus).
++
++ The text input should also handle all preedit_style and preedit_cursor
++ events occurring directly before preedit_string.
++ </description>
++ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++ <arg name="text" type="string"/>
++ <arg name="commit" type="string"/>
++ </event>
++
++ <enum name="preedit_style">
++ <entry name="default" value="0" summary="default style for composing text"/>
++ <entry name="none" value="1" summary="style should be the same as in non-composing text"/>
++ <entry name="active" value="2"/>
++ <entry name="inactive" value="3"/>
++ <entry name="highlight" value="4"/>
++ <entry name="underline" value="5"/>
++ <entry name="selection" value="6"/>
++ <entry name="incorrect" value="7"/>
++ </enum>
++
++ <event name="preedit_styling">
++ <description summary="pre-edit styling">
++ Sets styling information on composing text. The style is applied for
++ length bytes from index relative to the beginning of the composing
++ text (as byte offset). Multiple styles can
++ be applied to a composing text by sending multiple preedit_styling
++ events.
++
++ This event is handled as part of a following preedit_string event.
++ </description>
++ <arg name="index" type="uint"/>
++ <arg name="length" type="uint"/>
++ <arg name="style" type="uint" enum="preedit_style" />
++ </event>
++
++ <event name="preedit_cursor">
++ <description summary="pre-edit cursor">
++ Sets the cursor position inside the composing text (as byte
++ offset) relative to the start of the composing text. When index is a
++ negative number no cursor is shown.
++
++ This event is handled as part of a following preedit_string event.
++ </description>
++ <arg name="index" type="int"/>
++ </event>
++
++ <event name="commit_string">
++ <description summary="commit">
++ Notify when text should be inserted into the editor widget. The text to
++ commit could be either just a single character after a key press or the
++ result of some composing (pre-edit). It could also be an empty text
++ when some text should be removed (see delete_surrounding_text) or when
++ the input cursor should be moved (see cursor_position).
++
++ Any previously set composing text should be removed.
++ </description>
++ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++ <arg name="text" type="string"/>
++ </event>
++
++ <event name="cursor_position">
++ <description summary="set cursor to new position">
++ Notify when the cursor or anchor position should be modified.
++
++ This event should be handled as part of a following commit_string
++ event.
++ </description>
++ <arg name="index" type="int"/>
++ <arg name="anchor" type="int"/>
++ </event>
++
++ <event name="delete_surrounding_text">
++ <description summary="delete surrounding text">
++ Notify when the text around the current cursor position should be
++ deleted.
++
++ Index is relative to the current cursor (in bytes).
++ Length is the length of deleted text (in bytes).
++
++ This event should be handled as part of a following commit_string
++ event.
++ </description>
++ <arg name="index" type="int"/>
++ <arg name="length" type="uint"/>
++ </event>
++
++ <event name="keysym">
++ <description summary="keysym">
++ Notify when a key event was sent. Key events should not be used
++ for normal text input operations, which should be done with
++ commit_string, delete_surrounding_text, etc. The key event follows
++ the wl_keyboard key event convention. Sym is an XKB keysym, state a
++ wl_keyboard key_state. Modifiers are a mask for effective modifiers
++ (where the modifier indices are set by the modifiers_map event)
++ </description>
++ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++ <arg name="time" type="uint"/>
++ <arg name="sym" type="uint"/>
++ <arg name="state" type="uint"/>
++ <arg name="modifiers" type="uint"/>
++ </event>
++
++ <event name="language">
++ <description summary="language">
++ Sets the language of the input text. The "language" argument is an
++ RFC-3066 format language tag.
++ </description>
++ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++ <arg name="language" type="string"/>
++ </event>
++
++ <enum name="text_direction">
++ <entry name="auto" value="0" summary="automatic text direction based on text and language"/>
++ <entry name="ltr" value="1" summary="left-to-right"/>
++ <entry name="rtl" value="2" summary="right-to-left"/>
++ </enum>
++
++ <event name="text_direction">
++ <description summary="text direction">
++ Sets the text direction of input text.
++
++ It is mainly needed for showing an input cursor on the correct side of
++ the editor when there is no input done yet and making sure neutral
++ direction text is laid out properly.
++ </description>
++ <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++ <arg name="direction" type="uint" enum="text_direction" />
++ </event>
++ </interface>
++
++ <interface name="zwp_text_input_manager_v1" version="1">
++ <description summary="text input manager">
++ A factory for text_input objects. This object is a global singleton.
++ </description>
++
++ <request name="create_text_input">
++ <description summary="create text input">
++ Creates a new text_input object.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_text_input_v1"/>
++ </request>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++
++<protocol name="text_input_unstable_v3">
++ <copyright>
++ Copyright © 2012, 2013 Intel Corporation
++ Copyright © 2015, 2016 Jan Arne Petersen
++ Copyright © 2017, 2018 Red Hat, Inc.
++ Copyright © 2018 Purism SPC
++
++ Permission to use, copy, modify, distribute, and sell this
++ software and its documentation for any purpose is hereby granted
++ without fee, provided that the above copyright notice appear in
++ all copies and that both that copyright notice and this permission
++ notice appear in supporting documentation, and that the name of
++ the copyright holders not be used in advertising or publicity
++ pertaining to distribution of the software without specific,
++ written prior permission. The copyright holders make no
++ representations about the suitability of this software for any
++ purpose. It is provided "as is" without express or implied
++ warranty.
++
++ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
++ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
++ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
++ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
++ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
++ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
++ THIS SOFTWARE.
++ </copyright>
++
++ <description summary="Protocol for composing text">
++ This protocol allows compositors to act as input methods and to send text
++ to applications. A text input object is used to manage state of what are
++ typically text entry fields in the application.
++
++ This document adheres to the RFC 2119 when using words like "must",
++ "should", "may", etc.
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible changes
++ may be added together with the corresponding interface version bump.
++ Backward incompatible changes are done by bumping the version number in
++ the protocol and interface names and resetting the interface version.
++ Once the protocol is to be declared stable, the 'z' prefix and the
++ version number in the protocol and interface names are removed and the
++ interface version number is reset.
++ </description>
++
++ <interface name="zwp_text_input_v3" version="1">
++ <description summary="text input">
++ The zwp_text_input_v3 interface represents text input and input methods
++ associated with a seat. It provides enter/leave events to follow the
++ text input focus for a seat.
++
++ Requests are used to enable/disable the text-input object and set
++ state information like surrounding and selected text or the content type.
++ The information about the entered text is sent to the text-input object
++ via the preedit_string and commit_string events.
++
++ Text is valid UTF-8 encoded, indices and lengths are in bytes. Indices
++ must not point to middle bytes inside a code point: they must either
++ point to the first byte of a code point or to the end of the buffer.
++ Lengths must be measured between two valid indices.
++
++ Focus moving throughout surfaces will result in the emission of
++ zwp_text_input_v3.enter and zwp_text_input_v3.leave events. The focused
++ surface must commit zwp_text_input_v3.enable and
++ zwp_text_input_v3.disable requests as the keyboard focus moves across
++ editable and non-editable elements of the UI. Those two requests are not
++ expected to be paired with each other, the compositor must be able to
++ handle consecutive series of the same request.
++
++ State is sent by the state requests (set_surrounding_text,
++ set_content_type and set_cursor_rectangle) and a commit request. After an
++ enter event or disable request all state information is invalidated and
++ needs to be resent by the client.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="Destroy the wp_text_input">
++ Destroy the wp_text_input object. Also disables all surfaces enabled
++ through this wp_text_input object.
++ </description>
++ </request>
++
++ <request name="enable">
++ <description summary="Request text input to be enabled">
++ Requests text input on the surface previously obtained from the enter
++ event.
++
++ This request must be issued every time the active text input changes
++ to a new one, including within the current surface. Use
++ zwp_text_input_v3.disable when there is no longer any input focus on
++ the current surface.
++
++ Clients must not enable more than one text input on the single seat
++ and should disable the current text input before enabling the new one.
++ At most one instance of text input may be in enabled state per instance,
++ Requests to enable the another text input when some text input is active
++ must be ignored by compositor.
++
++ This request resets all state associated with previous enable, disable,
++ set_surrounding_text, set_text_change_cause, set_content_type, and
++ set_cursor_rectangle requests, as well as the state associated with
++ preedit_string, commit_string, and delete_surrounding_text events.
++
++ The set_surrounding_text, set_content_type and set_cursor_rectangle
++ requests must follow if the text input supports the necessary
++ functionality.
++
++ State set with this request is double-buffered. It will get applied on
++ the next zwp_text_input_v3.commit request, and stay valid until the
++ next committed enable or disable request.
++
++ The changes must be applied by the compositor after issuing a
++ zwp_text_input_v3.commit request.
++ </description>
++ </request>
++
++ <request name="disable">
++ <description summary="Disable text input on a surface">
++ Explicitly disable text input on the current surface (typically when
++ there is no focus on any text entry inside the surface).
++
++ State set with this request is double-buffered. It will get applied on
++ the next zwp_text_input_v3.commit request.
++ </description>
++ </request>
++
++ <request name="set_surrounding_text">
++ <description summary="sets the surrounding text">
++ Sets the surrounding plain text around the input, excluding the preedit
++ text.
++
++ The client should notify the compositor of any changes in any of the
++ values carried with this request, including changes caused by handling
++ incoming text-input events as well as changes caused by other
++ mechanisms like keyboard typing.
++
++ If the client is unaware of the text around the cursor, it should not
++ issue this request, to signify lack of support to the compositor.
++
++ Text is UTF-8 encoded, and should include the cursor position, the
++ complete selection and additional characters before and after them.
++ There is a maximum length of wayland messages, so text can not be
++ longer than 4000 bytes.
++
++ Cursor is the byte offset of the cursor within text buffer.
++
++ Anchor is the byte offset of the selection anchor within text buffer.
++ If there is no selected text, anchor is the same as cursor.
++
++ If any preedit text is present, it is replaced with a cursor for the
++ purpose of this event.
++
++ Values set with this request are double-buffered. They will get applied
++ on the next zwp_text_input_v3.commit request, and stay valid until the
++ next committed enable or disable request.
++
++ The initial state for affected fields is empty, meaning that the text
++ input does not support sending surrounding text. If the empty values
++ get applied, subsequent attempts to change them may have no effect.
++ </description>
++ <arg name="text" type="string"/>
++ <arg name="cursor" type="int"/>
++ <arg name="anchor" type="int"/>
++ </request>
++
++ <enum name="change_cause">
++ <description summary="text change reason">
++ Reason for the change of surrounding text or cursor posision.
++ </description>
++ <entry name="input_method" value="0" summary="input method caused the change"/>
++ <entry name="other" value="1" summary="something else than the input method caused the change"/>
++ </enum>
++
++ <request name="set_text_change_cause">
++ <description summary="indicates the cause of surrounding text change">
++ Tells the compositor why the text surrounding the cursor changed.
++
++ Whenever the client detects an external change in text, cursor, or
++ anchor posision, it must issue this request to the compositor. This
++ request is intended to give the input method a chance to update the
++ preedit text in an appropriate way, e.g. by removing it when the user
++ starts typing with a keyboard.
++
++ cause describes the source of the change.
++
++ The value set with this request is double-buffered. It must be applied
++ and reset to initial at the next zwp_text_input_v3.commit request.
++
++ The initial value of cause is input_method.
++ </description>
++ <arg name="cause" type="uint" enum="change_cause"/>
++ </request>
++
++ <enum name="content_hint" bitfield="true">
++ <description summary="content hint">
++ Content hint is a bitmask to allow to modify the behavior of the text
++ input.
++ </description>
++ <entry name="none" value="0x0" summary="no special behavior"/>
++ <entry name="completion" value="0x1" summary="suggest word completions"/>
++ <entry name="spellcheck" value="0x2" summary="suggest word corrections"/>
++ <entry name="auto_capitalization" value="0x4" summary="switch to uppercase letters at the start of a sentence"/>
++ <entry name="lowercase" value="0x8" summary="prefer lowercase letters"/>
++ <entry name="uppercase" value="0x10" summary="prefer uppercase letters"/>
++ <entry name="titlecase" value="0x20" summary="prefer casing for titles and headings (can be language dependent)"/>
++ <entry name="hidden_text" value="0x40" summary="characters should be hidden"/>
++ <entry name="sensitive_data" value="0x80" summary="typed text should not be stored"/>
++ <entry name="latin" value="0x100" summary="just Latin characters should be entered"/>
++ <entry name="multiline" value="0x200" summary="the text input is multiline"/>
++ </enum>
++
++ <enum name="content_purpose">
++ <description summary="content purpose">
++ The content purpose allows to specify the primary purpose of a text
++ input.
++
++ This allows an input method to show special purpose input panels with
++ extra characters or to disallow some characters.
++ </description>
++ <entry name="normal" value="0" summary="default input, allowing all characters"/>
++ <entry name="alpha" value="1" summary="allow only alphabetic characters"/>
++ <entry name="digits" value="2" summary="allow only digits"/>
++ <entry name="number" value="3" summary="input a number (including decimal separator and sign)"/>
++ <entry name="phone" value="4" summary="input a phone number"/>
++ <entry name="url" value="5" summary="input an URL"/>
++ <entry name="email" value="6" summary="input an email address"/>
++ <entry name="name" value="7" summary="input a name of a person"/>
++ <entry name="password" value="8" summary="input a password (combine with sensitive_data hint)"/>
++ <entry name="pin" value="9" summary="input is a numeric password (combine with sensitive_data hint)"/>
++ <entry name="date" value="10" summary="input a date"/>
++ <entry name="time" value="11" summary="input a time"/>
++ <entry name="datetime" value="12" summary="input a date and time"/>
++ <entry name="terminal" value="13" summary="input for a terminal"/>
++ </enum>
++
++ <request name="set_content_type">
++ <description summary="set content purpose and hint">
++ Sets the content purpose and content hint. While the purpose is the
++ basic purpose of an input field, the hint flags allow to modify some of
++ the behavior.
++
++ Values set with this request are double-buffered. They will get applied
++ on the next zwp_text_input_v3.commit request.
++ Subsequent attempts to update them may have no effect. The values
++ remain valid until the next committed enable or disable request.
++
++ The initial value for hint is none, and the initial value for purpose
++ is normal.
++ </description>
++ <arg name="hint" type="uint" enum="content_hint"/>
++ <arg name="purpose" type="uint" enum="content_purpose"/>
++ </request>
++
++ <request name="set_cursor_rectangle">
++ <description summary="set cursor position">
++ Marks an area around the cursor as a x, y, width, height rectangle in
++ surface local coordinates.
++
++ Allows the compositor to put a window with word suggestions near the
++ cursor, without obstructing the text being input.
++
++ If the client is unaware of the position of edited text, it should not
++ issue this request, to signify lack of support to the compositor.
++
++ Values set with this request are double-buffered. They will get applied
++ on the next zwp_text_input_v3.commit request, and stay valid until the
++ next committed enable or disable request.
++
++ The initial values describing a cursor rectangle are empty. That means
++ the text input does not support describing the cursor area. If the
++ empty values get applied, subsequent attempts to change them may have
++ no effect.
++ </description>
++ <arg name="x" type="int"/>
++ <arg name="y" type="int"/>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ </request>
++
++ <request name="commit">
++ <description summary="commit state">
++ Atomically applies state changes recently sent to the compositor.
++
++ The commit request establishes and updates the state of the client, and
++ must be issued after any changes to apply them.
++
++ Text input state (enabled status, content purpose, content hint,
++ surrounding text and change cause, cursor rectangle) is conceptually
++ double-buffered within the context of a text input, i.e. between a
++ committed enable request and the following committed enable or disable
++ request.
++
++ Protocol requests modify the pending state, as opposed to the current
++ state in use by the input method. A commit request atomically applies
++ all pending state, replacing the current state. After commit, the new
++ pending state is as documented for each related request.
++
++ Requests are applied in the order of arrival.
++
++ Neither current nor pending state are modified unless noted otherwise.
++
++ The compositor must count the number of commit requests coming from
++ each zwp_text_input_v3 object and use the count as the serial in done
++ events.
++ </description>
++ </request>
++
++ <event name="enter">
++ <description summary="enter event">
++ Notification that this seat's text-input focus is on a certain surface.
++
++ If client has created multiple text input objects, compositor must send
++ this event to all of them.
++
++ When the seat has the keyboard capability the text-input focus follows
++ the keyboard focus. This event sets the current surface for the
++ text-input object.
++ </description>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ </event>
++
++ <event name="leave">
++ <description summary="leave event">
++ Notification that this seat's text-input focus is no longer on a
++ certain surface. The client should reset any preedit string previously
++ set.
++
++ The leave notification clears the current surface. It is sent before
++ the enter notification for the new focus. After leave event, compositor
++ must ignore requests from any text input instances until next enter
++ event.
++
++ When the seat has the keyboard capability the text-input focus follows
++ the keyboard focus.
++ </description>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ </event>
++
++ <event name="preedit_string">
++ <description summary="pre-edit">
++ Notify when a new composing text (pre-edit) should be set at the
++ current cursor position. Any previously set composing text must be
++ removed. Any previously existing selected text must be removed.
++
++ The argument text contains the pre-edit string buffer.
++
++ The parameters cursor_begin and cursor_end are counted in bytes
++ relative to the beginning of the submitted text buffer. Cursor should
++ be hidden when both are equal to -1.
++
++ They could be represented by the client as a line if both values are
++ the same, or as a text highlight otherwise.
++
++ Values set with this event are double-buffered. They must be applied
++ and reset to initial on the next zwp_text_input_v3.done event.
++
++ The initial value of text is an empty string, and cursor_begin,
++ cursor_end and cursor_hidden are all 0.
++ </description>
++ <arg name="text" type="string" allow-null="true"/>
++ <arg name="cursor_begin" type="int"/>
++ <arg name="cursor_end" type="int"/>
++ </event>
++
++ <event name="commit_string">
++ <description summary="text commit">
++ Notify when text should be inserted into the editor widget. The text to
++ commit could be either just a single character after a key press or the
++ result of some composing (pre-edit).
++
++ Values set with this event are double-buffered. They must be applied
++ and reset to initial on the next zwp_text_input_v3.done event.
++
++ The initial value of text is an empty string.
++ </description>
++ <arg name="text" type="string" allow-null="true"/>
++ </event>
++
++ <event name="delete_surrounding_text">
++ <description summary="delete surrounding text">
++ Notify when the text around the current cursor position should be
++ deleted.
++
++ Before_length and after_length are the number of bytes before and after
++ the current cursor index (excluding the selection) to delete.
++
++ If a preedit text is present, in effect before_length is counted from
++ the beginning of it, and after_length from its end (see done event
++ sequence).
++
++ Values set with this event are double-buffered. They must be applied
++ and reset to initial on the next zwp_text_input_v3.done event.
++
++ The initial values of both before_length and after_length are 0.
++ </description>
++ <arg name="before_length" type="uint" summary="length of text before current cursor position"/>
++ <arg name="after_length" type="uint" summary="length of text after current cursor position"/>
++ </event>
++
++ <event name="done">
++ <description summary="apply changes">
++ Instruct the application to apply changes to state requested by the
++ preedit_string, commit_string and delete_surrounding_text events. The
++ state relating to these events is double-buffered, and each one
++ modifies the pending state. This event replaces the current state with
++ the pending state.
++
++ The application must proceed by evaluating the changes in the following
++ order:
++
++ 1. Replace existing preedit string with the cursor.
++ 2. Delete requested surrounding text.
++ 3. Insert commit string with the cursor at its end.
++ 4. Calculate surrounding text to send.
++ 5. Insert new preedit text in cursor position.
++ 6. Place cursor inside preedit text.
++
++ The serial number reflects the last state of the zwp_text_input_v3
++ object known to the compositor. The value of the serial argument must
++ be equal to the number of commit requests already issued on that object.
++
++ When the client receives a done event with a serial different than the
++ number of past commit requests, it must proceed with evaluating and
++ applying the changes as normal, except it should not change the current
++ state of the zwp_text_input_v3 object. All pending state requests
++ (set_surrounding_text, set_content_type and set_cursor_rectangle) on
++ the zwp_text_input_v3 object should be sent and committed after
++ receiving a zwp_text_input_v3.done event with a matching serial.
++ </description>
++ <arg name="serial" type="uint"/>
++ </event>
++ </interface>
++
++ <interface name="zwp_text_input_manager_v3" version="1">
++ <description summary="text input manager">
++ A factory for text-input objects. This object is a global singleton.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="Destroy the wp_text_input_manager">
++ Destroy the wp_text_input_manager object.
++ </description>
++ </request>
++
++ <request name="get_text_input">
++ <description summary="create a new text input object">
++ Creates a new text-input object for a given seat.
++ </description>
++ <arg name="id" type="new_id" interface="zwp_text_input_v3"/>
++ <arg name="seat" type="object" interface="wl_seat"/>
++ </request>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++xdg_decoration protocol
++
++Maintainers:
++Simon Ser <contact@emersion.fr>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_decoration_unstable_v1">
++ <copyright>
++ Copyright © 2018 Simon Ser
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="zxdg_decoration_manager_v1" version="1">
++ <description summary="window decoration manager">
++ This interface allows a compositor to announce support for server-side
++ decorations.
++
++ A window decoration is a set of window controls as deemed appropriate by
++ the party managing them, such as user interface components used to move,
++ resize and change a window's state.
++
++ A client can use this protocol to request being decorated by a supporting
++ compositor.
++
++ If compositor and client do not negotiate the use of a server-side
++ decoration using this protocol, clients continue to self-decorate as they
++ see fit.
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible changes
++ may be added together with the corresponding interface version bump.
++ Backward incompatible changes are done by bumping the version number in
++ the protocol and interface names and resetting the interface version.
++ Once the protocol is to be declared stable, the 'z' prefix and the
++ version number in the protocol and interface names are removed and the
++ interface version number is reset.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the decoration manager object">
++ Destroy the decoration manager. This doesn't destroy objects created
++ with the manager.
++ </description>
++ </request>
++
++ <request name="get_toplevel_decoration">
++ <description summary="create a new toplevel decoration object">
++ Create a new decoration object associated with the given toplevel.
++
++ Creating an xdg_toplevel_decoration from an xdg_toplevel which has a
++ buffer attached or committed is a client error, and any attempts by a
++ client to attach or manipulate a buffer prior to the first
++ xdg_toplevel_decoration.configure event must also be treated as
++ errors.
++ </description>
++ <arg name="id" type="new_id" interface="zxdg_toplevel_decoration_v1"/>
++ <arg name="toplevel" type="object" interface="xdg_toplevel"/>
++ </request>
++ </interface>
++
++ <interface name="zxdg_toplevel_decoration_v1" version="1">
++ <description summary="decoration object for a toplevel surface">
++ The decoration object allows the compositor to toggle server-side window
++ decorations for a toplevel surface. The client can request to switch to
++ another mode.
++
++ The xdg_toplevel_decoration object must be destroyed before its
++ xdg_toplevel.
++ </description>
++
++ <enum name="error">
++ <entry name="unconfigured_buffer" value="0"
++ summary="xdg_toplevel has a buffer attached before configure"/>
++ <entry name="already_constructed" value="1"
++ summary="xdg_toplevel already has a decoration object"/>
++ <entry name="orphaned" value="2"
++ summary="xdg_toplevel destroyed before the decoration object"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the decoration object">
++ Switch back to a mode without any server-side decorations at the next
++ commit.
++ </description>
++ </request>
++
++ <enum name="mode">
++ <description summary="window decoration modes">
++ These values describe window decoration modes.
++ </description>
++ <entry name="client_side" value="1"
++ summary="no server-side window decoration"/>
++ <entry name="server_side" value="2"
++ summary="server-side window decoration"/>
++ </enum>
++
++ <request name="set_mode">
++ <description summary="set the decoration mode">
++ Set the toplevel surface decoration mode. This informs the compositor
++ that the client prefers the provided decoration mode.
++
++ After requesting a decoration mode, the compositor will respond by
++ emitting an xdg_surface.configure event. The client should then update
++ its content, drawing it without decorations if the received mode is
++ server-side decorations. The client must also acknowledge the configure
++ when committing the new content (see xdg_surface.ack_configure).
++
++ The compositor can decide not to use the client's mode and enforce a
++ different mode instead.
++
++ Clients whose decoration mode depend on the xdg_toplevel state may send
++ a set_mode request in response to an xdg_surface.configure event and wait
++ for the next xdg_surface.configure event to prevent unwanted state.
++ Such clients are responsible for preventing configure loops and must
++ make sure not to send multiple successive set_mode requests with the
++ same decoration mode.
++ </description>
++ <arg name="mode" type="uint" enum="mode" summary="the decoration mode"/>
++ </request>
++
++ <request name="unset_mode">
++ <description summary="unset the decoration mode">
++ Unset the toplevel surface decoration mode. This informs the compositor
++ that the client doesn't prefer a particular decoration mode.
++
++ This request has the same semantics as set_mode.
++ </description>
++ </request>
++
++ <event name="configure">
++ <description summary="suggest a surface change">
++ The configure event asks the client to change its decoration mode. The
++ configured state should not be applied immediately. Clients must send an
++ ack_configure in response to this event. See xdg_surface.configure and
++ xdg_surface.ack_configure for details.
++
++ A configure event can be sent at any time. The specified mode must be
++ obeyed by the client.
++ </description>
++ <arg name="mode" type="uint" enum="mode" summary="the decoration mode"/>
++ </event>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++xdg foreign protocol
++
++Maintainers:
++Jonas Ådahl <jadahl@gmail.com>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_foreign_unstable_v1">
++
++ <copyright>
++ Copyright © 2015-2016 Red Hat Inc.
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <description summary="Protocol for exporting xdg surface handles">
++ This protocol specifies a way for making it possible to reference a surface
++ of a different client. With such a reference, a client can, by using the
++ interfaces provided by this protocol, manipulate the relationship between
++ its own surfaces and the surface of some other client. For example, stack
++ some of its own surface above the other clients surface.
++
++ In order for a client A to get a reference of a surface of client B, client
++ B must first export its surface using xdg_exporter.export. Upon doing this,
++ client B will receive a handle (a unique string) that it may share with
++ client A in some way (for example D-Bus). After client A has received the
++ handle from client B, it may use xdg_importer.import to create a reference
++ to the surface client B just exported. See the corresponding requests for
++ details.
++
++ A possible use case for this is out-of-process dialogs. For example when a
++ sandboxed client without file system access needs the user to select a file
++ on the file system, given sandbox environment support, it can export its
++ surface, passing the exported surface handle to an unsandboxed process that
++ can show a file browser dialog and stack it above the sandboxed client's
++ surface.
++
++ Warning! The protocol described in this file is experimental and backward
++ incompatible changes may be made. Backward compatible changes may be added
++ together with the corresponding interface version bump. Backward
++ incompatible changes are done by bumping the version number in the protocol
++ and interface names and resetting the interface version. Once the protocol
++ is to be declared stable, the 'z' prefix and the version number in the
++ protocol and interface names are removed and the interface version number is
++ reset.
++ </description>
++
++ <interface name="zxdg_exporter_v1" version="1">
++ <description summary="interface for exporting surfaces">
++ A global interface used for exporting surfaces that can later be imported
++ using xdg_importer.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_exporter object">
++ Notify the compositor that the xdg_exporter object will no longer be
++ used.
++ </description>
++ </request>
++
++ <request name="export">
++ <description summary="export a surface">
++ The export request exports the passed surface so that it can later be
++ imported via xdg_importer. When called, a new xdg_exported object will
++ be created and xdg_exported.handle will be sent immediately. See the
++ corresponding interface and event for details.
++
++ A surface may be exported multiple times, and each exported handle may
++ be used to create an xdg_imported multiple times. Only xdg_surface
++ surfaces may be exported.
++ </description>
++ <arg name="id" type="new_id" interface="zxdg_exported_v1"
++ summary="the new xdg_exported object"/>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="the surface to export"/>
++ </request>
++ </interface>
++
++ <interface name="zxdg_importer_v1" version="1">
++ <description summary="interface for importing surfaces">
++ A global interface used for importing surfaces exported by xdg_exporter.
++ With this interface, a client can create a reference to a surface of
++ another client.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_importer object">
++ Notify the compositor that the xdg_importer object will no longer be
++ used.
++ </description>
++ </request>
++
++ <request name="import">
++ <description summary="import a surface">
++ The import request imports a surface from any client given a handle
++ retrieved by exporting said surface using xdg_exporter.export. When
++ called, a new xdg_imported object will be created. This new object
++ represents the imported surface, and the importing client can
++ manipulate its relationship using it. See xdg_imported for details.
++ </description>
++ <arg name="id" type="new_id" interface="zxdg_imported_v1"
++ summary="the new xdg_imported object"/>
++ <arg name="handle" type="string"
++ summary="the exported surface handle"/>
++ </request>
++ </interface>
++
++ <interface name="zxdg_exported_v1" version="1">
++ <description summary="an exported surface handle">
++ An xdg_exported object represents an exported reference to a surface. The
++ exported surface may be referenced as long as the xdg_exported object not
++ destroyed. Destroying the xdg_exported invalidates any relationship the
++ importer may have established using xdg_imported.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="unexport the exported surface">
++ Revoke the previously exported surface. This invalidates any
++ relationship the importer may have set up using the xdg_imported created
++ given the handle sent via xdg_exported.handle.
++ </description>
++ </request>
++
++ <event name="handle">
++ <description summary="the exported surface handle">
++ The handle event contains the unique handle of this exported surface
++ reference. It may be shared with any client, which then can use it to
++ import the surface by calling xdg_importer.import. A handle may be
++ used to import the surface multiple times.
++ </description>
++ <arg name="handle" type="string" summary="the exported surface handle"/>
++ </event>
++ </interface>
++
++ <interface name="zxdg_imported_v1" version="1">
++ <description summary="an imported surface handle">
++ An xdg_imported object represents an imported reference to surface exported
++ by some client. A client can use this interface to manipulate
++ relationships between its own surfaces and the imported surface.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_imported object">
++ Notify the compositor that it will no longer use the xdg_imported
++ object. Any relationship that may have been set up will at this point
++ be invalidated.
++ </description>
++ </request>
++
++ <request name="set_parent_of">
++ <description summary="set as the parent of some surface">
++ Set the imported surface as the parent of some surface of the client.
++ The passed surface must be a toplevel xdg_surface. Calling this function
++ sets up a surface to surface relation with the same stacking and positioning
++ semantics as xdg_surface.set_parent.
++ </description>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="the child surface"/>
++ </request>
++
++ <event name="destroyed">
++ <description summary="the imported surface handle has been destroyed">
++ The imported surface handle has been destroyed and any relationship set
++ up has been invalidated. This may happen for various reasons, for
++ example if the exported surface or the exported surface handle has been
++ destroyed, if the handle used for importing was invalid.
++ </description>
++ </event>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_foreign_unstable_v2">
++
++ <copyright>
++ Copyright © 2015-2016 Red Hat Inc.
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <description summary="Protocol for exporting xdg surface handles">
++ This protocol specifies a way for making it possible to reference a surface
++ of a different client. With such a reference, a client can, by using the
++ interfaces provided by this protocol, manipulate the relationship between
++ its own surfaces and the surface of some other client. For example, stack
++ some of its own surface above the other clients surface.
++
++ In order for a client A to get a reference of a surface of client B, client
++ B must first export its surface using xdg_exporter.export_toplevel. Upon
++ doing this, client B will receive a handle (a unique string) that it may
++ share with client A in some way (for example D-Bus). After client A has
++ received the handle from client B, it may use xdg_importer.import_toplevel
++ to create a reference to the surface client B just exported. See the
++ corresponding requests for details.
++
++ A possible use case for this is out-of-process dialogs. For example when a
++ sandboxed client without file system access needs the user to select a file
++ on the file system, given sandbox environment support, it can export its
++ surface, passing the exported surface handle to an unsandboxed process that
++ can show a file browser dialog and stack it above the sandboxed client's
++ surface.
++
++ Warning! The protocol described in this file is experimental and backward
++ incompatible changes may be made. Backward compatible changes may be added
++ together with the corresponding interface version bump. Backward
++ incompatible changes are done by bumping the version number in the protocol
++ and interface names and resetting the interface version. Once the protocol
++ is to be declared stable, the 'z' prefix and the version number in the
++ protocol and interface names are removed and the interface version number is
++ reset.
++ </description>
++
++ <interface name="zxdg_exporter_v2" version="1">
++ <description summary="interface for exporting surfaces">
++ A global interface used for exporting surfaces that can later be imported
++ using xdg_importer.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_exporter object">
++ Notify the compositor that the xdg_exporter object will no longer be
++ used.
++ </description>
++ </request>
++
++ <enum name="error">
++ <description summary="error values">
++ These errors can be emitted in response to invalid xdg_exporter
++ requests.
++ </description>
++ <entry name="invalid_surface" value="0" summary="surface is not an xdg_toplevel"/>
++ </enum>
++
++ <request name="export_toplevel">
++ <description summary="export a toplevel surface">
++ The export_toplevel request exports the passed surface so that it can later be
++ imported via xdg_importer. When called, a new xdg_exported object will
++ be created and xdg_exported.handle will be sent immediately. See the
++ corresponding interface and event for details.
++
++ A surface may be exported multiple times, and each exported handle may
++ be used to create an xdg_imported multiple times. Only xdg_toplevel
++ equivalent surfaces may be exported, otherwise an invalid_surface
++ protocol error is sent.
++ </description>
++ <arg name="id" type="new_id" interface="zxdg_exported_v2"
++ summary="the new xdg_exported object"/>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="the surface to export"/>
++ </request>
++ </interface>
++
++ <interface name="zxdg_importer_v2" version="1">
++ <description summary="interface for importing surfaces">
++ A global interface used for importing surfaces exported by xdg_exporter.
++ With this interface, a client can create a reference to a surface of
++ another client.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_importer object">
++ Notify the compositor that the xdg_importer object will no longer be
++ used.
++ </description>
++ </request>
++
++ <request name="import_toplevel">
++ <description summary="import a toplevel surface">
++ The import_toplevel request imports a surface from any client given a handle
++ retrieved by exporting said surface using xdg_exporter.export_toplevel.
++ When called, a new xdg_imported object will be created. This new object
++ represents the imported surface, and the importing client can
++ manipulate its relationship using it. See xdg_imported for details.
++ </description>
++ <arg name="id" type="new_id" interface="zxdg_imported_v2"
++ summary="the new xdg_imported object"/>
++ <arg name="handle" type="string"
++ summary="the exported surface handle"/>
++ </request>
++ </interface>
++
++ <interface name="zxdg_exported_v2" version="1">
++ <description summary="an exported surface handle">
++ An xdg_exported object represents an exported reference to a surface. The
++ exported surface may be referenced as long as the xdg_exported object not
++ destroyed. Destroying the xdg_exported invalidates any relationship the
++ importer may have established using xdg_imported.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="unexport the exported surface">
++ Revoke the previously exported surface. This invalidates any
++ relationship the importer may have set up using the xdg_imported created
++ given the handle sent via xdg_exported.handle.
++ </description>
++ </request>
++
++ <event name="handle">
++ <description summary="the exported surface handle">
++ The handle event contains the unique handle of this exported surface
++ reference. It may be shared with any client, which then can use it to
++ import the surface by calling xdg_importer.import_toplevel. A handle
++ may be used to import the surface multiple times.
++ </description>
++ <arg name="handle" type="string" summary="the exported surface handle"/>
++ </event>
++ </interface>
++
++ <interface name="zxdg_imported_v2" version="1">
++ <description summary="an imported surface handle">
++ An xdg_imported object represents an imported reference to surface exported
++ by some client. A client can use this interface to manipulate
++ relationships between its own surfaces and the imported surface.
++ </description>
++
++ <enum name="error">
++ <description summary="error values">
++ These errors can be emitted in response to invalid xdg_imported
++ requests.
++ </description>
++ <entry name="invalid_surface" value="0" summary="surface is not an xdg_toplevel"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_imported object">
++ Notify the compositor that it will no longer use the xdg_imported
++ object. Any relationship that may have been set up will at this point
++ be invalidated.
++ </description>
++ </request>
++
++ <request name="set_parent_of">
++ <description summary="set as the parent of some surface">
++ Set the imported surface as the parent of some surface of the client.
++ The passed surface must be an xdg_toplevel equivalent, otherwise an
++ invalid_surface protocol error is sent. Calling this function sets up
++ a surface to surface relation with the same stacking and positioning
++ semantics as xdg_toplevel.set_parent.
++ </description>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="the child surface"/>
++ </request>
++
++ <event name="destroyed">
++ <description summary="the imported surface handle has been destroyed">
++ The imported surface handle has been destroyed and any relationship set
++ up has been invalidated. This may happen for various reasons, for
++ example if the exported surface or the exported surface handle has been
++ destroyed, if the handle used for importing was invalid.
++ </description>
++ </event>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++xdg_output protocol
++
++Maintainers:
++Olivier Fourdan <ofourdan@redhat.com>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_output_unstable_v1">
++
++ <copyright>
++ Copyright © 2017 Red Hat Inc.
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <description summary="Protocol to describe output regions">
++ This protocol aims at describing outputs in a way which is more in line
++ with the concept of an output on desktop oriented systems.
++
++ Some information are more specific to the concept of an output for
++ a desktop oriented system and may not make sense in other applications,
++ such as IVI systems for example.
++
++ Typically, the global compositor space on a desktop system is made of
++ a contiguous or overlapping set of rectangular regions.
++
++ Some of the information provided in this protocol might be identical
++ to their counterparts already available from wl_output, in which case
++ the information provided by this protocol should be preferred to their
++ equivalent in wl_output. The goal is to move the desktop specific
++ concepts (such as output location within the global compositor space,
++ the connector name and types, etc.) out of the core wl_output protocol.
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible
++ changes may be added together with the corresponding interface
++ version bump.
++ Backward incompatible changes are done by bumping the version
++ number in the protocol and interface names and resetting the
++ interface version. Once the protocol is to be declared stable,
++ the 'z' prefix and the version number in the protocol and
++ interface names are removed and the interface version number is
++ reset.
++ </description>
++
++ <interface name="zxdg_output_manager_v1" version="3">
++ <description summary="manage xdg_output objects">
++ A global factory interface for xdg_output objects.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_output_manager object">
++ Using this request a client can tell the server that it is not
++ going to use the xdg_output_manager object anymore.
++
++ Any objects already created through this instance are not affected.
++ </description>
++ </request>
++
++ <request name="get_xdg_output">
++ <description summary="create an xdg output from a wl_output">
++ This creates a new xdg_output object for the given wl_output.
++ </description>
++ <arg name="id" type="new_id" interface="zxdg_output_v1"/>
++ <arg name="output" type="object" interface="wl_output"/>
++ </request>
++ </interface>
++
++ <interface name="zxdg_output_v1" version="3">
++ <description summary="compositor logical output region">
++ An xdg_output describes part of the compositor geometry.
++
++ This typically corresponds to a monitor that displays part of the
++ compositor space.
++
++ For objects version 3 onwards, after all xdg_output properties have been
++ sent (when the object is created and when properties are updated), a
++ wl_output.done event is sent. This allows changes to the output
++ properties to be seen as atomic, even if they happen via multiple events.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_output object">
++ Using this request a client can tell the server that it is not
++ going to use the xdg_output object anymore.
++ </description>
++ </request>
++
++ <event name="logical_position">
++ <description summary="position of the output within the global compositor space">
++ The position event describes the location of the wl_output within
++ the global compositor space.
++
++ The logical_position event is sent after creating an xdg_output
++ (see xdg_output_manager.get_xdg_output) and whenever the location
++ of the output changes within the global compositor space.
++ </description>
++ <arg name="x" type="int"
++ summary="x position within the global compositor space"/>
++ <arg name="y" type="int"
++ summary="y position within the global compositor space"/>
++ </event>
++
++ <event name="logical_size">
++ <description summary="size of the output in the global compositor space">
++ The logical_size event describes the size of the output in the
++ global compositor space.
++
++ For example, a surface without any buffer scale, transformation
++ nor rotation set, with the size matching the logical_size will
++ have the same size as the corresponding output when displayed.
++
++ Most regular Wayland clients should not pay attention to the
++ logical size and would rather rely on xdg_shell interfaces.
++
++ Some clients such as Xwayland, however, need this to configure
++ their surfaces in the global compositor space as the compositor
++ may apply a different scale from what is advertised by the output
++ scaling property (to achieve fractional scaling, for example).
++
++ For example, for a wl_output mode 3840×2160 and a scale factor 2:
++
++ - A compositor not scaling the surface buffers will advertise a
++ logical size of 3840×2160,
++
++ - A compositor automatically scaling the surface buffers will
++ advertise a logical size of 1920×1080,
++
++ - A compositor using a fractional scale of 1.5 will advertise a
++ logical size of 2560×1440.
++
++ For example, for a wl_output mode 1920×1080 and a 90 degree rotation,
++ the compositor will advertise a logical size of 1080x1920.
++
++ The logical_size event is sent after creating an xdg_output
++ (see xdg_output_manager.get_xdg_output) and whenever the logical
++ size of the output changes, either as a result of a change in the
++ applied scale or because of a change in the corresponding output
++ mode(see wl_output.mode) or transform (see wl_output.transform).
++ </description>
++ <arg name="width" type="int"
++ summary="width in global compositor space"/>
++ <arg name="height" type="int"
++ summary="height in global compositor space"/>
++ </event>
++
++ <event name="done">
++ <description summary="all information about the output have been sent">
++ This event is sent after all other properties of an xdg_output
++ have been sent.
++
++ This allows changes to the xdg_output properties to be seen as
++ atomic, even if they happen via multiple events.
++
++ For objects version 3 onwards, this event is deprecated. Compositors
++ are not required to send it anymore and must send wl_output.done
++ instead.
++ </description>
++ </event>
++
++ <!-- Version 2 additions -->
++
++ <event name="name" since="2">
++ <description summary="name of this output">
++ Many compositors will assign names to their outputs, show them to the
++ user, allow them to be configured by name, etc. The client may wish to
++ know this name as well to offer the user similar behaviors.
++
++ The naming convention is compositor defined, but limited to
++ alphanumeric characters and dashes (-). Each name is unique among all
++ wl_output globals, but if a wl_output global is destroyed the same name
++ may be reused later. The names will also remain consistent across
++ sessions with the same hardware and software configuration.
++
++ Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do
++ not assume that the name is a reflection of an underlying DRM
++ connector, X11 connection, etc.
++
++ The name event is sent after creating an xdg_output (see
++ xdg_output_manager.get_xdg_output). This event is only sent once per
++ xdg_output, and the name does not change over the lifetime of the
++ wl_output global.
++ </description>
++ <arg name="name" type="string" summary="output name"/>
++ </event>
++
++ <event name="description" since="2">
++ <description summary="human-readable description of this output">
++ Many compositors can produce human-readable descriptions of their
++ outputs. The client may wish to know this description as well, to
++ communicate the user for various purposes.
++
++ The description is a UTF-8 string with no convention defined for its
++ contents. Examples might include 'Foocorp 11" Display' or 'Virtual X11
++ output via :1'.
++
++ The description event is sent after creating an xdg_output (see
++ xdg_output_manager.get_xdg_output) and whenever the description
++ changes. The description is optional, and may not be sent at all.
++
++ For objects of version 2 and lower, this event is only sent once per
++ xdg_output, and the description does not change over the lifetime of
++ the wl_output global.
++ </description>
++ <arg name="description" type="string" summary="output description"/>
++ </event>
++
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++xdg shell protocol
++
++Maintainers:
++Jasper St. Pierre <jstpierre@mecheye.net>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_shell_unstable_v5">
++
++ <copyright>
++ Copyright © 2008-2013 Kristian Høgsberg
++ Copyright © 2013 Rafael Antognolli
++ Copyright © 2013 Jasper St. Pierre
++ Copyright © 2010-2013 Intel Corporation
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="xdg_shell" version="1">
++ <description summary="create desktop-style surfaces">
++ xdg_shell allows clients to turn a wl_surface into a "real window"
++ which can be dragged, resized, stacked, and moved around by the
++ user. Everything about this interface is suited towards traditional
++ desktop environments.
++ </description>
++
++ <enum name="version">
++ <description summary="latest protocol version">
++ The 'current' member of this enum gives the version of the
++ protocol. Implementations can compare this to the version
++ they implement using static_assert to ensure the protocol and
++ implementation versions match.
++ </description>
++ <entry name="current" value="5" summary="Always the latest version"/>
++ </enum>
++
++ <enum name="error">
++ <entry name="role" value="0" summary="given wl_surface has another role"/>
++ <entry name="defunct_surfaces" value="1" summary="xdg_shell was destroyed before children"/>
++ <entry name="not_the_topmost_popup" value="2" summary="the client tried to map or destroy a non-topmost popup"/>
++ <entry name="invalid_popup_parent" value="3" summary="the client specified an invalid popup parent surface"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy xdg_shell">
++ Destroy this xdg_shell object.
++
++ Destroying a bound xdg_shell object while there are surfaces
++ still alive created by this xdg_shell object instance is illegal
++ and will result in a protocol error.
++ </description>
++ </request>
++
++ <request name="use_unstable_version">
++ <description summary="enable use of this unstable version">
++ Negotiate the unstable version of the interface. This
++ mechanism is in place to ensure client and server agree on the
++ unstable versions of the protocol that they speak or exit
++ cleanly if they don't agree. This request will go away once
++ the xdg-shell protocol is stable.
++ </description>
++ <arg name="version" type="int"/>
++ </request>
++
++ <request name="get_xdg_surface">
++ <description summary="create a shell surface from a surface">
++ This creates an xdg_surface for the given surface and gives it the
++ xdg_surface role. A wl_surface can only be given an xdg_surface role
++ once. If get_xdg_surface is called with a wl_surface that already has
++ an active xdg_surface associated with it, or if it had any other role,
++ an error is raised.
++
++ See the documentation of xdg_surface for more details about what an
++ xdg_surface is and how it is used.
++ </description>
++ <arg name="id" type="new_id" interface="xdg_surface"/>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ </request>
++
++ <request name="get_xdg_popup">
++ <description summary="create a popup for a surface">
++ This creates an xdg_popup for the given surface and gives it the
++ xdg_popup role. A wl_surface can only be given an xdg_popup role
++ once. If get_xdg_popup is called with a wl_surface that already has
++ an active xdg_popup associated with it, or if it had any other role,
++ an error is raised.
++
++ This request must be used in response to some sort of user action
++ like a button press, key press, or touch down event.
++
++ See the documentation of xdg_popup for more details about what an
++ xdg_popup is and how it is used.
++ </description>
++ <arg name="id" type="new_id" interface="xdg_popup"/>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ <arg name="parent" type="object" interface="wl_surface"/>
++ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++ <arg name="serial" type="uint" summary="the serial of the user event"/>
++ <arg name="x" type="int"/>
++ <arg name="y" type="int"/>
++ </request>
++
++ <event name="ping">
++ <description summary="check if the client is alive">
++ The ping event asks the client if it's still alive. Pass the
++ serial specified in the event back to the compositor by sending
++ a "pong" request back with the specified serial.
++
++ Compositors can use this to determine if the client is still
++ alive. It's unspecified what will happen if the client doesn't
++ respond to the ping request, or in what timeframe. Clients should
++ try to respond in a reasonable amount of time.
++
++ A compositor is free to ping in any way it wants, but a client must
++ always respond to any xdg_shell object it created.
++ </description>
++ <arg name="serial" type="uint" summary="pass this to the pong request"/>
++ </event>
++
++ <request name="pong">
++ <description summary="respond to a ping event">
++ A client must respond to a ping event with a pong request or
++ the client may be deemed unresponsive.
++ </description>
++ <arg name="serial" type="uint" summary="serial of the ping event"/>
++ </request>
++ </interface>
++
++ <interface name="xdg_surface" version="1">
++ <description summary="A desktop window">
++ An interface that may be implemented by a wl_surface, for
++ implementations that provide a desktop-style user interface.
++
++ It provides requests to treat surfaces like windows, allowing to set
++ properties like maximized, fullscreen, minimized, and to move and resize
++ them, and associate metadata like title and app id.
++
++ The client must call wl_surface.commit on the corresponding wl_surface
++ for the xdg_surface state to take effect. Prior to committing the new
++ state, it can set up initial configuration, such as maximizing or setting
++ a window geometry.
++
++ Even without attaching a buffer the compositor must respond to initial
++ committed configuration, for instance sending a configure event with
++ expected window geometry if the client maximized its surface during
++ initialization.
++
++ For a surface to be mapped by the compositor the client must have
++ committed both an xdg_surface state and a buffer.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="Destroy the xdg_surface">
++ Unmap and destroy the window. The window will be effectively
++ hidden from the user's point of view, and all state like
++ maximization, fullscreen, and so on, will be lost.
++ </description>
++ </request>
++
++ <request name="set_parent">
++ <description summary="set the parent of this surface">
++ Set the "parent" of this surface. This window should be stacked
++ above a parent. The parent surface must be mapped as long as this
++ surface is mapped.
++
++ Parent windows should be set on dialogs, toolboxes, or other
++ "auxiliary" surfaces, so that the parent is raised when the dialog
++ is raised.
++ </description>
++ <arg name="parent" type="object" interface="xdg_surface" allow-null="true"/>
++ </request>
++
++ <request name="set_title">
++ <description summary="set surface title">
++ Set a short title for the surface.
++
++ This string may be used to identify the surface in a task bar,
++ window list, or other user interface elements provided by the
++ compositor.
++
++ The string must be encoded in UTF-8.
++ </description>
++ <arg name="title" type="string"/>
++ </request>
++
++ <request name="set_app_id">
++ <description summary="set application ID">
++ Set an application identifier for the surface.
++
++ The app ID identifies the general class of applications to which
++ the surface belongs. The compositor can use this to group multiple
++ surfaces together, or to determine how to launch a new application.
++
++ For D-Bus activatable applications, the app ID is used as the D-Bus
++ service name.
++
++ The compositor shell will try to group application surfaces together
++ by their app ID. As a best practice, it is suggested to select app
++ ID's that match the basename of the application's .desktop file.
++ For example, "org.freedesktop.FooViewer" where the .desktop file is
++ "org.freedesktop.FooViewer.desktop".
++
++ See the desktop-entry specification [0] for more details on
++ application identifiers and how they relate to well-known D-Bus
++ names and .desktop files.
++
++ [0] http://standards.freedesktop.org/desktop-entry-spec/
++ </description>
++ <arg name="app_id" type="string"/>
++ </request>
++
++ <request name="show_window_menu">
++ <description summary="show the window menu">
++ Clients implementing client-side decorations might want to show
++ a context menu when right-clicking on the decorations, giving the
++ user a menu that they can use to maximize or minimize the window.
++
++ This request asks the compositor to pop up such a window menu at
++ the given position, relative to the local surface coordinates of
++ the parent surface. There are no guarantees as to what menu items
++ the window menu contains.
++
++ This request must be used in response to some sort of user action
++ like a button press, key press, or touch down event.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++ <arg name="serial" type="uint" summary="the serial of the user event"/>
++ <arg name="x" type="int" summary="the x position to pop up the window menu at"/>
++ <arg name="y" type="int" summary="the y position to pop up the window menu at"/>
++ </request>
++
++ <request name="move">
++ <description summary="start an interactive move">
++ Start an interactive, user-driven move of the surface.
++
++ This request must be used in response to some sort of user action
++ like a button press, key press, or touch down event. The passed
++ serial is used to determine the type of interactive move (touch,
++ pointer, etc).
++
++ The server may ignore move requests depending on the state of
++ the surface (e.g. fullscreen or maximized), or if the passed serial
++ is no longer valid.
++
++ If triggered, the surface will lose the focus of the device
++ (wl_pointer, wl_touch, etc) used for the move. It is up to the
++ compositor to visually indicate that the move is taking place, such as
++ updating a pointer cursor, during the move. There is no guarantee
++ that the device focus will return when the move is completed.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++ <arg name="serial" type="uint" summary="the serial of the user event"/>
++ </request>
++
++ <enum name="resize_edge">
++ <description summary="edge values for resizing">
++ These values are used to indicate which edge of a surface
++ is being dragged in a resize operation.
++ </description>
++ <entry name="none" value="0"/>
++ <entry name="top" value="1"/>
++ <entry name="bottom" value="2"/>
++ <entry name="left" value="4"/>
++ <entry name="top_left" value="5"/>
++ <entry name="bottom_left" value="6"/>
++ <entry name="right" value="8"/>
++ <entry name="top_right" value="9"/>
++ <entry name="bottom_right" value="10"/>
++ </enum>
++
++ <request name="resize">
++ <description summary="start an interactive resize">
++ Start a user-driven, interactive resize of the surface.
++
++ This request must be used in response to some sort of user action
++ like a button press, key press, or touch down event. The passed
++ serial is used to determine the type of interactive resize (touch,
++ pointer, etc).
++
++ The server may ignore resize requests depending on the state of
++ the surface (e.g. fullscreen or maximized).
++
++ If triggered, the client will receive configure events with the
++ "resize" state enum value and the expected sizes. See the "resize"
++ enum value for more details about what is required. The client
++ must also acknowledge configure events using "ack_configure". After
++ the resize is completed, the client will receive another "configure"
++ event without the resize state.
++
++ If triggered, the surface also will lose the focus of the device
++ (wl_pointer, wl_touch, etc) used for the resize. It is up to the
++ compositor to visually indicate that the resize is taking place,
++ such as updating a pointer cursor, during the resize. There is no
++ guarantee that the device focus will return when the resize is
++ completed.
++
++ The edges parameter specifies how the surface should be resized,
++ and is one of the values of the resize_edge enum. The compositor
++ may use this information to update the surface position for
++ example when dragging the top left corner. The compositor may also
++ use this information to adapt its behavior, e.g. choose an
++ appropriate cursor image.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++ <arg name="serial" type="uint" summary="the serial of the user event"/>
++ <arg name="edges" type="uint" summary="which edge or corner is being dragged"/>
++ </request>
++
++ <enum name="state">
++ <description summary="types of state on the surface">
++ The different state values used on the surface. This is designed for
++ state values like maximized, fullscreen. It is paired with the
++ configure event to ensure that both the client and the compositor
++ setting the state can be synchronized.
++
++ States set in this way are double-buffered. They will get applied on
++ the next commit.
++
++ Desktop environments may extend this enum by taking up a range of
++ values and documenting the range they chose in this description.
++ They are not required to document the values for the range that they
++ chose. Ideally, any good extensions from a desktop environment should
++ make its way into standardization into this enum.
++
++ The current reserved ranges are:
++
++ 0x0000 - 0x0FFF: xdg-shell core values, documented below.
++ 0x1000 - 0x1FFF: GNOME
++ 0x2000 - 0x2FFF: EFL
++ </description>
++ <entry name="maximized" value="1" summary="the surface is maximized">
++ <description summary="the surface is maximized">
++ The surface is maximized. The window geometry specified in the configure
++ event must be obeyed by the client.
++ </description>
++ </entry>
++ <entry name="fullscreen" value="2" summary="the surface is fullscreen">
++ <description summary="the surface is fullscreen">
++ The surface is fullscreen. The window geometry specified in the configure
++ event must be obeyed by the client.
++ </description>
++ </entry>
++ <entry name="resizing" value="3" summary="the surface is being resized">
++ <description summary="the surface is being resized">
++ The surface is being resized. The window geometry specified in the
++ configure event is a maximum; the client cannot resize beyond it.
++ Clients that have aspect ratio or cell sizing configuration can use
++ a smaller size, however.
++ </description>
++ </entry>
++ <entry name="activated" value="4" summary="the surface is now activated">
++ <description summary="the surface is now activated">
++ Client window decorations should be painted as if the window is
++ active. Do not assume this means that the window actually has
++ keyboard or pointer focus.
++ </description>
++ </entry>
++ </enum>
++
++ <event name="configure">
++ <description summary="suggest a surface change">
++ The configure event asks the client to resize its surface or to
++ change its state.
++
++ The width and height arguments specify a hint to the window
++ about how its surface should be resized in window geometry
++ coordinates. See set_window_geometry.
++
++ If the width or height arguments are zero, it means the client
++ should decide its own window dimension. This may happen when the
++ compositor need to configure the state of the surface but doesn't
++ have any information about any previous or expected dimension.
++
++ The states listed in the event specify how the width/height
++ arguments should be interpreted, and possibly how it should be
++ drawn.
++
++ Clients should arrange their surface for the new size and
++ states, and then send a ack_configure request with the serial
++ sent in this configure event at some point before committing
++ the new surface.
++
++ If the client receives multiple configure events before it
++ can respond to one, it is free to discard all but the last
++ event it received.
++ </description>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ <arg name="states" type="array"/>
++ <arg name="serial" type="uint"/>
++ </event>
++
++ <request name="ack_configure">
++ <description summary="ack a configure event">
++ When a configure event is received, if a client commits the
++ surface in response to the configure event, then the client
++ must make an ack_configure request sometime before the commit
++ request, passing along the serial of the configure event.
++
++ For instance, the compositor might use this information to move
++ a surface to the top left only when the client has drawn itself
++ for the maximized or fullscreen state.
++
++ If the client receives multiple configure events before it
++ can respond to one, it only has to ack the last configure event.
++
++ A client is not required to commit immediately after sending
++ an ack_configure request - it may even ack_configure several times
++ before its next surface commit.
++
++ The compositor expects that the most recently received
++ ack_configure request at the time of a commit indicates which
++ configure event the client is responding to.
++ </description>
++ <arg name="serial" type="uint" summary="the serial from the configure event"/>
++ </request>
++
++ <request name="set_window_geometry">
++ <description summary="set the new window geometry">
++ The window geometry of a window is its "visible bounds" from the
++ user's perspective. Client-side decorations often have invisible
++ portions like drop-shadows which should be ignored for the
++ purposes of aligning, placing and constraining windows.
++
++ The window geometry is double buffered, and will be applied at the
++ time wl_surface.commit of the corresponding wl_surface is called.
++
++ Once the window geometry of the surface is set once, it is not
++ possible to unset it, and it will remain the same until
++ set_window_geometry is called again, even if a new subsurface or
++ buffer is attached.
++
++ If never set, the value is the full bounds of the surface,
++ including any subsurfaces. This updates dynamically on every
++ commit. This unset mode is meant for extremely simple clients.
++
++ If responding to a configure event, the window geometry in here
++ must respect the sizing negotiations specified by the states in
++ the configure event.
++
++ The arguments are given in the surface local coordinate space of
++ the wl_surface associated with this xdg_surface.
++
++ The width and height must be greater than zero.
++ </description>
++ <arg name="x" type="int"/>
++ <arg name="y" type="int"/>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ </request>
++
++ <request name="set_maximized">
++ <description summary="maximize the window">
++ Maximize the surface.
++
++ After requesting that the surface should be maximized, the compositor
++ will respond by emitting a configure event with the "maximized" state
++ and the required window geometry. The client should then update its
++ content, drawing it in a maximized state, i.e. without shadow or other
++ decoration outside of the window geometry. The client must also
++ acknowledge the configure when committing the new content (see
++ ack_configure).
++
++ It is up to the compositor to decide how and where to maximize the
++ surface, for example which output and what region of the screen should
++ be used.
++
++ If the surface was already maximized, the compositor will still emit
++ a configure event with the "maximized" state.
++ </description>
++ </request>
++
++ <request name="unset_maximized">
++ <description summary="unmaximize the window">
++ Unmaximize the surface.
++
++ After requesting that the surface should be unmaximized, the compositor
++ will respond by emitting a configure event without the "maximized"
++ state. If available, the compositor will include the window geometry
++ dimensions the window had prior to being maximized in the configure
++ request. The client must then update its content, drawing it in a
++ regular state, i.e. potentially with shadow, etc. The client must also
++ acknowledge the configure when committing the new content (see
++ ack_configure).
++
++ It is up to the compositor to position the surface after it was
++ unmaximized; usually the position the surface had before maximizing, if
++ applicable.
++
++ If the surface was already not maximized, the compositor will still
++ emit a configure event without the "maximized" state.
++ </description>
++ </request>
++
++ <request name="set_fullscreen">
++ <description summary="set the window as fullscreen on a monitor">
++ Make the surface fullscreen.
++
++ You can specify an output that you would prefer to be fullscreen.
++ If this value is NULL, it's up to the compositor to choose which
++ display will be used to map this surface.
++
++ If the surface doesn't cover the whole output, the compositor will
++ position the surface in the center of the output and compensate with
++ black borders filling the rest of the output.
++ </description>
++ <arg name="output" type="object" interface="wl_output" allow-null="true"/>
++ </request>
++ <request name="unset_fullscreen" />
++
++ <request name="set_minimized">
++ <description summary="set the window as minimized">
++ Request that the compositor minimize your surface. There is no
++ way to know if the surface is currently minimized, nor is there
++ any way to unset minimization on this surface.
++
++ If you are looking to throttle redrawing when minimized, please
++ instead use the wl_surface.frame event for this, as this will
++ also work with live previews on windows in Alt-Tab, Expose or
++ similar compositor features.
++ </description>
++ </request>
++
++ <event name="close">
++ <description summary="surface wants to be closed">
++ The close event is sent by the compositor when the user
++ wants the surface to be closed. This should be equivalent to
++ the user clicking the close button in client-side decorations,
++ if your application has any...
++
++ This is only a request that the user intends to close your
++ window. The client may choose to ignore this request, or show
++ a dialog to ask the user to save their data...
++ </description>
++ </event>
++ </interface>
++
++ <interface name="xdg_popup" version="1">
++ <description summary="short-lived, popup surfaces for menus">
++ A popup surface is a short-lived, temporary surface that can be
++ used to implement menus. It takes an explicit grab on the surface
++ that will be dismissed when the user dismisses the popup. This can
++ be done by the user clicking outside the surface, using the keyboard,
++ or even locking the screen through closing the lid or a timeout.
++
++ When the popup is dismissed, a popup_done event will be sent out,
++ and at the same time the surface will be unmapped. The xdg_popup
++ object is now inert and cannot be reactivated, so clients should
++ destroy it. Explicitly destroying the xdg_popup object will also
++ dismiss the popup and unmap the surface.
++
++ Clients will receive events for all their surfaces during this
++ grab (which is an "owner-events" grab in X11 parlance). This is
++ done so that users can navigate through submenus and other
++ "nested" popup windows without having to dismiss the topmost
++ popup.
++
++ Clients that want to dismiss the popup when another surface of
++ their own is clicked should dismiss the popup using the destroy
++ request.
++
++ The parent surface must have either an xdg_surface or xdg_popup
++ role.
++
++ Specifying an xdg_popup for the parent means that the popups are
++ nested, with this popup now being the topmost popup. Nested
++ popups must be destroyed in the reverse order they were created
++ in, e.g. the only popup you are allowed to destroy at all times
++ is the topmost one.
++
++ If there is an existing popup when creating a new popup, the
++ parent must be the current topmost popup.
++
++ A parent surface must be mapped before the new popup is mapped.
++
++ When compositors choose to dismiss a popup, they will likely
++ dismiss every nested popup as well. When a compositor dismisses
++ popups, it will follow the same dismissing order as required
++ from the client.
++
++ The x and y arguments passed when creating the popup object specify
++ where the top left of the popup should be placed, relative to the
++ local surface coordinates of the parent surface. See
++ xdg_shell.get_xdg_popup.
++
++ The client must call wl_surface.commit on the corresponding wl_surface
++ for the xdg_popup state to take effect.
++
++ For a surface to be mapped by the compositor the client must have
++ committed both the xdg_popup state and a buffer.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="remove xdg_popup interface">
++ This destroys the popup. Explicitly destroying the xdg_popup
++ object will also dismiss the popup, and unmap the surface.
++
++ If this xdg_popup is not the "topmost" popup, a protocol error
++ will be sent.
++ </description>
++ </request>
++
++ <event name="popup_done">
++ <description summary="popup interaction is done">
++ The popup_done event is sent out when a popup is dismissed by the
++ compositor. The client should destroy the xdg_popup object at this
++ point.
++ </description>
++ </event>
++
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_shell_unstable_v6">
++
++ <copyright>
++ Copyright © 2008-2013 Kristian Høgsberg
++ Copyright © 2013 Rafael Antognolli
++ Copyright © 2013 Jasper St. Pierre
++ Copyright © 2010-2013 Intel Corporation
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <interface name="zxdg_shell_v6" version="1">
++ <description summary="create desktop-style surfaces">
++ xdg_shell allows clients to turn a wl_surface into a "real window"
++ which can be dragged, resized, stacked, and moved around by the
++ user. Everything about this interface is suited towards traditional
++ desktop environments.
++ </description>
++
++ <enum name="error">
++ <entry name="role" value="0" summary="given wl_surface has another role"/>
++ <entry name="defunct_surfaces" value="1"
++ summary="xdg_shell was destroyed before children"/>
++ <entry name="not_the_topmost_popup" value="2"
++ summary="the client tried to map or destroy a non-topmost popup"/>
++ <entry name="invalid_popup_parent" value="3"
++ summary="the client specified an invalid popup parent surface"/>
++ <entry name="invalid_surface_state" value="4"
++ summary="the client provided an invalid surface state"/>
++ <entry name="invalid_positioner" value="5"
++ summary="the client provided an invalid positioner"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy xdg_shell">
++ Destroy this xdg_shell object.
++
++ Destroying a bound xdg_shell object while there are surfaces
++ still alive created by this xdg_shell object instance is illegal
++ and will result in a protocol error.
++ </description>
++ </request>
++
++ <request name="create_positioner">
++ <description summary="create a positioner object">
++ Create a positioner object. A positioner object is used to position
++ surfaces relative to some parent surface. See the interface description
++ and xdg_surface.get_popup for details.
++ </description>
++ <arg name="id" type="new_id" interface="zxdg_positioner_v6"/>
++ </request>
++
++ <request name="get_xdg_surface">
++ <description summary="create a shell surface from a surface">
++ This creates an xdg_surface for the given surface. While xdg_surface
++ itself is not a role, the corresponding surface may only be assigned
++ a role extending xdg_surface, such as xdg_toplevel or xdg_popup.
++
++ This creates an xdg_surface for the given surface. An xdg_surface is
++ used as basis to define a role to a given surface, such as xdg_toplevel
++ or xdg_popup. It also manages functionality shared between xdg_surface
++ based surface roles.
++
++ See the documentation of xdg_surface for more details about what an
++ xdg_surface is and how it is used.
++ </description>
++ <arg name="id" type="new_id" interface="zxdg_surface_v6"/>
++ <arg name="surface" type="object" interface="wl_surface"/>
++ </request>
++
++ <request name="pong">
++ <description summary="respond to a ping event">
++ A client must respond to a ping event with a pong request or
++ the client may be deemed unresponsive. See xdg_shell.ping.
++ </description>
++ <arg name="serial" type="uint" summary="serial of the ping event"/>
++ </request>
++
++ <event name="ping">
++ <description summary="check if the client is alive">
++ The ping event asks the client if it's still alive. Pass the
++ serial specified in the event back to the compositor by sending
++ a "pong" request back with the specified serial. See xdg_shell.ping.
++
++ Compositors can use this to determine if the client is still
++ alive. It's unspecified what will happen if the client doesn't
++ respond to the ping request, or in what timeframe. Clients should
++ try to respond in a reasonable amount of time.
++
++ A compositor is free to ping in any way it wants, but a client must
++ always respond to any xdg_shell object it created.
++ </description>
++ <arg name="serial" type="uint" summary="pass this to the pong request"/>
++ </event>
++ </interface>
++
++ <interface name="zxdg_positioner_v6" version="1">
++ <description summary="child surface positioner">
++ The xdg_positioner provides a collection of rules for the placement of a
++ child surface relative to a parent surface. Rules can be defined to ensure
++ the child surface remains within the visible area's borders, and to
++ specify how the child surface changes its position, such as sliding along
++ an axis, or flipping around a rectangle. These positioner-created rules are
++ constrained by the requirement that a child surface must intersect with or
++ be at least partially adjacent to its parent surface.
++
++ See the various requests for details about possible rules.
++
++ At the time of the request, the compositor makes a copy of the rules
++ specified by the xdg_positioner. Thus, after the request is complete the
++ xdg_positioner object can be destroyed or reused; further changes to the
++ object will have no effect on previous usages.
++
++ For an xdg_positioner object to be considered complete, it must have a
++ non-zero size set by set_size, and a non-zero anchor rectangle set by
++ set_anchor_rect. Passing an incomplete xdg_positioner object when
++ positioning a surface raises an error.
++ </description>
++
++ <enum name="error">
++ <entry name="invalid_input" value="0" summary="invalid input provided"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_positioner object">
++ Notify the compositor that the xdg_positioner will no longer be used.
++ </description>
++ </request>
++
++ <request name="set_size">
++ <description summary="set the size of the to-be positioned rectangle">
++ Set the size of the surface that is to be positioned with the positioner
++ object. The size is in surface-local coordinates and corresponds to the
++ window geometry. See xdg_surface.set_window_geometry.
++
++ If a zero or negative size is set the invalid_input error is raised.
++ </description>
++ <arg name="width" type="int" summary="width of positioned rectangle"/>
++ <arg name="height" type="int" summary="height of positioned rectangle"/>
++ </request>
++
++ <request name="set_anchor_rect">
++ <description summary="set the anchor rectangle within the parent surface">
++ Specify the anchor rectangle within the parent surface that the child
++ surface will be placed relative to. The rectangle is relative to the
++ window geometry as defined by xdg_surface.set_window_geometry of the
++ parent surface. The rectangle must be at least 1x1 large.
++
++ When the xdg_positioner object is used to position a child surface, the
++ anchor rectangle may not extend outside the window geometry of the
++ positioned child's parent surface.
++
++ If a zero or negative size is set the invalid_input error is raised.
++ </description>
++ <arg name="x" type="int" summary="x position of anchor rectangle"/>
++ <arg name="y" type="int" summary="y position of anchor rectangle"/>
++ <arg name="width" type="int" summary="width of anchor rectangle"/>
++ <arg name="height" type="int" summary="height of anchor rectangle"/>
++ </request>
++
++ <enum name="anchor" bitfield="true">
++ <entry name="none" value="0"
++ summary="the center of the anchor rectangle"/>
++ <entry name="top" value="1"
++ summary="the top edge of the anchor rectangle"/>
++ <entry name="bottom" value="2"
++ summary="the bottom edge of the anchor rectangle"/>
++ <entry name="left" value="4"
++ summary="the left edge of the anchor rectangle"/>
++ <entry name="right" value="8"
++ summary="the right edge of the anchor rectangle"/>
++ </enum>
++
++ <request name="set_anchor">
++ <description summary="set anchor rectangle anchor edges">
++ Defines a set of edges for the anchor rectangle. These are used to
++ derive an anchor point that the child surface will be positioned
++ relative to. If two orthogonal edges are specified (e.g. 'top' and
++ 'left'), then the anchor point will be the intersection of the edges
++ (e.g. the top left position of the rectangle); otherwise, the derived
++ anchor point will be centered on the specified edge, or in the center of
++ the anchor rectangle if no edge is specified.
++
++ If two parallel anchor edges are specified (e.g. 'left' and 'right'),
++ the invalid_input error is raised.
++ </description>
++ <arg name="anchor" type="uint" enum="anchor"
++ summary="bit mask of anchor edges"/>
++ </request>
++
++ <enum name="gravity" bitfield="true">
++ <entry name="none" value="0"
++ summary="center over the anchor edge"/>
++ <entry name="top" value="1"
++ summary="position above the anchor edge"/>
++ <entry name="bottom" value="2"
++ summary="position below the anchor edge"/>
++ <entry name="left" value="4"
++ summary="position to the left of the anchor edge"/>
++ <entry name="right" value="8"
++ summary="position to the right of the anchor edge"/>
++ </enum>
++
++ <request name="set_gravity">
++ <description summary="set child surface gravity">
++ Defines in what direction a surface should be positioned, relative to
++ the anchor point of the parent surface. If two orthogonal gravities are
++ specified (e.g. 'bottom' and 'right'), then the child surface will be
++ placed in the specified direction; otherwise, the child surface will be
++ centered over the anchor point on any axis that had no gravity
++ specified.
++
++ If two parallel gravities are specified (e.g. 'left' and 'right'), the
++ invalid_input error is raised.
++ </description>
++ <arg name="gravity" type="uint" enum="gravity"
++ summary="bit mask of gravity directions"/>
++ </request>
++
++ <enum name="constraint_adjustment" bitfield="true">
++ <description summary="constraint adjustments">
++ The constraint adjustment value define ways the compositor will adjust
++ the position of the surface, if the unadjusted position would result
++ in the surface being partly constrained.
++
++ Whether a surface is considered 'constrained' is left to the compositor
++ to determine. For example, the surface may be partly outside the
++ compositor's defined 'work area', thus necessitating the child surface's
++ position be adjusted until it is entirely inside the work area.
++
++ The adjustments can be combined, according to a defined precedence: 1)
++ Flip, 2) Slide, 3) Resize.
++ </description>
++ <entry name="none" value="0">
++ <description summary="don't move the child surface when constrained">
++ Don't alter the surface position even if it is constrained on some
++ axis, for example partially outside the edge of a monitor.
++ </description>
++ </entry>
++ <entry name="slide_x" value="1">
++ <description summary="move along the x axis until unconstrained">
++ Slide the surface along the x axis until it is no longer constrained.
++
++ First try to slide towards the direction of the gravity on the x axis
++ until either the edge in the opposite direction of the gravity is
++ unconstrained or the edge in the direction of the gravity is
++ constrained.
++
++ Then try to slide towards the opposite direction of the gravity on the
++ x axis until either the edge in the direction of the gravity is
++ unconstrained or the edge in the opposite direction of the gravity is
++ constrained.
++ </description>
++ </entry>
++ <entry name="slide_y" value="2">
++ <description summary="move along the y axis until unconstrained">
++ Slide the surface along the y axis until it is no longer constrained.
++
++ First try to slide towards the direction of the gravity on the y axis
++ until either the edge in the opposite direction of the gravity is
++ unconstrained or the edge in the direction of the gravity is
++ constrained.
++
++ Then try to slide towards the opposite direction of the gravity on the
++ y axis until either the edge in the direction of the gravity is
++ unconstrained or the edge in the opposite direction of the gravity is
++ constrained.
++ </description>
++ </entry>
++ <entry name="flip_x" value="4">
++ <description summary="invert the anchor and gravity on the x axis">
++ Invert the anchor and gravity on the x axis if the surface is
++ constrained on the x axis. For example, if the left edge of the
++ surface is constrained, the gravity is 'left' and the anchor is
++ 'left', change the gravity to 'right' and the anchor to 'right'.
++
++ If the adjusted position also ends up being constrained, the resulting
++ position of the flip_x adjustment will be the one before the
++ adjustment.
++ </description>
++ </entry>
++ <entry name="flip_y" value="8">
++ <description summary="invert the anchor and gravity on the y axis">
++ Invert the anchor and gravity on the y axis if the surface is
++ constrained on the y axis. For example, if the bottom edge of the
++ surface is constrained, the gravity is 'bottom' and the anchor is
++ 'bottom', change the gravity to 'top' and the anchor to 'top'.
++
++ If the adjusted position also ends up being constrained, the resulting
++ position of the flip_y adjustment will be the one before the
++ adjustment.
++ </description>
++ </entry>
++ <entry name="resize_x" value="16">
++ <description summary="horizontally resize the surface">
++ Resize the surface horizontally so that it is completely
++ unconstrained.
++ </description>
++ </entry>
++ <entry name="resize_y" value="32">
++ <description summary="vertically resize the surface">
++ Resize the surface vertically so that it is completely unconstrained.
++ </description>
++ </entry>
++ </enum>
++
++ <request name="set_constraint_adjustment">
++ <description summary="set the adjustment to be done when constrained">
++ Specify how the window should be positioned if the originally intended
++ position caused the surface to be constrained, meaning at least
++ partially outside positioning boundaries set by the compositor. The
++ adjustment is set by constructing a bitmask describing the adjustment to
++ be made when the surface is constrained on that axis.
++
++ If no bit for one axis is set, the compositor will assume that the child
++ surface should not change its position on that axis when constrained.
++
++ If more than one bit for one axis is set, the order of how adjustments
++ are applied is specified in the corresponding adjustment descriptions.
++
++ The default adjustment is none.
++ </description>
++ <arg name="constraint_adjustment" type="uint"
++ summary="bit mask of constraint adjustments"/>
++ </request>
++
++ <request name="set_offset">
++ <description summary="set surface position offset">
++ Specify the surface position offset relative to the position of the
++ anchor on the anchor rectangle and the anchor on the surface. For
++ example if the anchor of the anchor rectangle is at (x, y), the surface
++ has the gravity bottom|right, and the offset is (ox, oy), the calculated
++ surface position will be (x + ox, y + oy). The offset position of the
++ surface is the one used for constraint testing. See
++ set_constraint_adjustment.
++
++ An example use case is placing a popup menu on top of a user interface
++ element, while aligning the user interface element of the parent surface
++ with some user interface element placed somewhere in the popup surface.
++ </description>
++ <arg name="x" type="int" summary="surface position x offset"/>
++ <arg name="y" type="int" summary="surface position y offset"/>
++ </request>
++ </interface>
++
++ <interface name="zxdg_surface_v6" version="1">
++ <description summary="desktop user interface surface base interface">
++ An interface that may be implemented by a wl_surface, for
++ implementations that provide a desktop-style user interface.
++
++ It provides a base set of functionality required to construct user
++ interface elements requiring management by the compositor, such as
++ toplevel windows, menus, etc. The types of functionality are split into
++ xdg_surface roles.
++
++ Creating an xdg_surface does not set the role for a wl_surface. In order
++ to map an xdg_surface, the client must create a role-specific object
++ using, e.g., get_toplevel, get_popup. The wl_surface for any given
++ xdg_surface can have at most one role, and may not be assigned any role
++ not based on xdg_surface.
++
++ A role must be assigned before any other requests are made to the
++ xdg_surface object.
++
++ The client must call wl_surface.commit on the corresponding wl_surface
++ for the xdg_surface state to take effect.
++
++ Creating an xdg_surface from a wl_surface which has a buffer attached or
++ committed is a client error, and any attempts by a client to attach or
++ manipulate a buffer prior to the first xdg_surface.configure call must
++ also be treated as errors.
++
++ For a surface to be mapped by the compositor, the following conditions
++ must be met: (1) the client has assigned an xdg_surface based role to the
++ surface, (2) the client has set and committed the xdg_surface state and
++ the role dependent state to the surface and (3) the client has committed a
++ buffer to the surface.
++ </description>
++
++ <enum name="error">
++ <entry name="not_constructed" value="1"/>
++ <entry name="already_constructed" value="2"/>
++ <entry name="unconfigured_buffer" value="3"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_surface">
++ Destroy the xdg_surface object. An xdg_surface must only be destroyed
++ after its role object has been destroyed.
++ </description>
++ </request>
++
++ <request name="get_toplevel">
++ <description summary="assign the xdg_toplevel surface role">
++ This creates an xdg_toplevel object for the given xdg_surface and gives
++ the associated wl_surface the xdg_toplevel role.
++
++ See the documentation of xdg_toplevel for more details about what an
++ xdg_toplevel is and how it is used.
++ </description>
++ <arg name="id" type="new_id" interface="zxdg_toplevel_v6"/>
++ </request>
++
++ <request name="get_popup">
++ <description summary="assign the xdg_popup surface role">
++ This creates an xdg_popup object for the given xdg_surface and gives the
++ associated wl_surface the xdg_popup role.
++
++ See the documentation of xdg_popup for more details about what an
++ xdg_popup is and how it is used.
++ </description>
++ <arg name="id" type="new_id" interface="zxdg_popup_v6"/>
++ <arg name="parent" type="object" interface="zxdg_surface_v6"/>
++ <arg name="positioner" type="object" interface="zxdg_positioner_v6"/>
++ </request>
++
++ <request name="set_window_geometry">
++ <description summary="set the new window geometry">
++ The window geometry of a surface is its "visible bounds" from the
++ user's perspective. Client-side decorations often have invisible
++ portions like drop-shadows which should be ignored for the
++ purposes of aligning, placing and constraining windows.
++
++ The window geometry is double buffered, and will be applied at the
++ time wl_surface.commit of the corresponding wl_surface is called.
++
++ Once the window geometry of the surface is set, it is not possible to
++ unset it, and it will remain the same until set_window_geometry is
++ called again, even if a new subsurface or buffer is attached.
++
++ If never set, the value is the full bounds of the surface,
++ including any subsurfaces. This updates dynamically on every
++ commit. This unset is meant for extremely simple clients.
++
++ The arguments are given in the surface-local coordinate space of
++ the wl_surface associated with this xdg_surface.
++
++ The width and height must be greater than zero. Setting an invalid size
++ will raise an error. When applied, the effective window geometry will be
++ the set window geometry clamped to the bounding rectangle of the
++ combined geometry of the surface of the xdg_surface and the associated
++ subsurfaces.
++ </description>
++ <arg name="x" type="int"/>
++ <arg name="y" type="int"/>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ </request>
++
++ <request name="ack_configure">
++ <description summary="ack a configure event">
++ When a configure event is received, if a client commits the
++ surface in response to the configure event, then the client
++ must make an ack_configure request sometime before the commit
++ request, passing along the serial of the configure event.
++
++ For instance, for toplevel surfaces the compositor might use this
++ information to move a surface to the top left only when the client has
++ drawn itself for the maximized or fullscreen state.
++
++ If the client receives multiple configure events before it
++ can respond to one, it only has to ack the last configure event.
++
++ A client is not required to commit immediately after sending
++ an ack_configure request - it may even ack_configure several times
++ before its next surface commit.
++
++ A client may send multiple ack_configure requests before committing, but
++ only the last request sent before a commit indicates which configure
++ event the client really is responding to.
++ </description>
++ <arg name="serial" type="uint" summary="the serial from the configure event"/>
++ </request>
++
++ <event name="configure">
++ <description summary="suggest a surface change">
++ The configure event marks the end of a configure sequence. A configure
++ sequence is a set of one or more events configuring the state of the
++ xdg_surface, including the final xdg_surface.configure event.
++
++ Where applicable, xdg_surface surface roles will during a configure
++ sequence extend this event as a latched state sent as events before the
++ xdg_surface.configure event. Such events should be considered to make up
++ a set of atomically applied configuration states, where the
++ xdg_surface.configure commits the accumulated state.
++
++ Clients should arrange their surface for the new states, and then send
++ an ack_configure request with the serial sent in this configure event at
++ some point before committing the new surface.
++
++ If the client receives multiple configure events before it can respond
++ to one, it is free to discard all but the last event it received.
++ </description>
++ <arg name="serial" type="uint" summary="serial of the configure event"/>
++ </event>
++ </interface>
++
++ <interface name="zxdg_toplevel_v6" version="1">
++ <description summary="toplevel surface">
++ This interface defines an xdg_surface role which allows a surface to,
++ among other things, set window-like properties such as maximize,
++ fullscreen, and minimize, set application-specific metadata like title and
++ id, and well as trigger user interactive operations such as interactive
++ resize and move.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the xdg_toplevel">
++ Unmap and destroy the window. The window will be effectively
++ hidden from the user's point of view, and all state like
++ maximization, fullscreen, and so on, will be lost.
++ </description>
++ </request>
++
++ <request name="set_parent">
++ <description summary="set the parent of this surface">
++ Set the "parent" of this surface. This window should be stacked
++ above a parent. The parent surface must be mapped as long as this
++ surface is mapped.
++
++ Parent windows should be set on dialogs, toolboxes, or other
++ "auxiliary" surfaces, so that the parent is raised when the dialog
++ is raised.
++ </description>
++ <arg name="parent" type="object" interface="zxdg_toplevel_v6" allow-null="true"/>
++ </request>
++
++ <request name="set_title">
++ <description summary="set surface title">
++ Set a short title for the surface.
++
++ This string may be used to identify the surface in a task bar,
++ window list, or other user interface elements provided by the
++ compositor.
++
++ The string must be encoded in UTF-8.
++ </description>
++ <arg name="title" type="string"/>
++ </request>
++
++ <request name="set_app_id">
++ <description summary="set application ID">
++ Set an application identifier for the surface.
++
++ The app ID identifies the general class of applications to which
++ the surface belongs. The compositor can use this to group multiple
++ surfaces together, or to determine how to launch a new application.
++
++ For D-Bus activatable applications, the app ID is used as the D-Bus
++ service name.
++
++ The compositor shell will try to group application surfaces together
++ by their app ID. As a best practice, it is suggested to select app
++ ID's that match the basename of the application's .desktop file.
++ For example, "org.freedesktop.FooViewer" where the .desktop file is
++ "org.freedesktop.FooViewer.desktop".
++
++ See the desktop-entry specification [0] for more details on
++ application identifiers and how they relate to well-known D-Bus
++ names and .desktop files.
++
++ [0] http://standards.freedesktop.org/desktop-entry-spec/
++ </description>
++ <arg name="app_id" type="string"/>
++ </request>
++
++ <request name="show_window_menu">
++ <description summary="show the window menu">
++ Clients implementing client-side decorations might want to show
++ a context menu when right-clicking on the decorations, giving the
++ user a menu that they can use to maximize or minimize the window.
++
++ This request asks the compositor to pop up such a window menu at
++ the given position, relative to the local surface coordinates of
++ the parent surface. There are no guarantees as to what menu items
++ the window menu contains.
++
++ This request must be used in response to some sort of user action
++ like a button press, key press, or touch down event.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++ <arg name="serial" type="uint" summary="the serial of the user event"/>
++ <arg name="x" type="int" summary="the x position to pop up the window menu at"/>
++ <arg name="y" type="int" summary="the y position to pop up the window menu at"/>
++ </request>
++
++ <request name="move">
++ <description summary="start an interactive move">
++ Start an interactive, user-driven move of the surface.
++
++ This request must be used in response to some sort of user action
++ like a button press, key press, or touch down event. The passed
++ serial is used to determine the type of interactive move (touch,
++ pointer, etc).
++
++ The server may ignore move requests depending on the state of
++ the surface (e.g. fullscreen or maximized), or if the passed serial
++ is no longer valid.
++
++ If triggered, the surface will lose the focus of the device
++ (wl_pointer, wl_touch, etc) used for the move. It is up to the
++ compositor to visually indicate that the move is taking place, such as
++ updating a pointer cursor, during the move. There is no guarantee
++ that the device focus will return when the move is completed.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++ <arg name="serial" type="uint" summary="the serial of the user event"/>
++ </request>
++
++ <enum name="resize_edge">
++ <description summary="edge values for resizing">
++ These values are used to indicate which edge of a surface
++ is being dragged in a resize operation.
++ </description>
++ <entry name="none" value="0"/>
++ <entry name="top" value="1"/>
++ <entry name="bottom" value="2"/>
++ <entry name="left" value="4"/>
++ <entry name="top_left" value="5"/>
++ <entry name="bottom_left" value="6"/>
++ <entry name="right" value="8"/>
++ <entry name="top_right" value="9"/>
++ <entry name="bottom_right" value="10"/>
++ </enum>
++
++ <request name="resize">
++ <description summary="start an interactive resize">
++ Start a user-driven, interactive resize of the surface.
++
++ This request must be used in response to some sort of user action
++ like a button press, key press, or touch down event. The passed
++ serial is used to determine the type of interactive resize (touch,
++ pointer, etc).
++
++ The server may ignore resize requests depending on the state of
++ the surface (e.g. fullscreen or maximized).
++
++ If triggered, the client will receive configure events with the
++ "resize" state enum value and the expected sizes. See the "resize"
++ enum value for more details about what is required. The client
++ must also acknowledge configure events using "ack_configure". After
++ the resize is completed, the client will receive another "configure"
++ event without the resize state.
++
++ If triggered, the surface also will lose the focus of the device
++ (wl_pointer, wl_touch, etc) used for the resize. It is up to the
++ compositor to visually indicate that the resize is taking place,
++ such as updating a pointer cursor, during the resize. There is no
++ guarantee that the device focus will return when the resize is
++ completed.
++
++ The edges parameter specifies how the surface should be resized,
++ and is one of the values of the resize_edge enum. The compositor
++ may use this information to update the surface position for
++ example when dragging the top left corner. The compositor may also
++ use this information to adapt its behavior, e.g. choose an
++ appropriate cursor image.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++ <arg name="serial" type="uint" summary="the serial of the user event"/>
++ <arg name="edges" type="uint" summary="which edge or corner is being dragged"/>
++ </request>
++
++ <enum name="state">
++ <description summary="types of state on the surface">
++ The different state values used on the surface. This is designed for
++ state values like maximized, fullscreen. It is paired with the
++ configure event to ensure that both the client and the compositor
++ setting the state can be synchronized.
++
++ States set in this way are double-buffered. They will get applied on
++ the next commit.
++ </description>
++ <entry name="maximized" value="1" summary="the surface is maximized">
++ <description summary="the surface is maximized">
++ The surface is maximized. The window geometry specified in the configure
++ event must be obeyed by the client.
++ </description>
++ </entry>
++ <entry name="fullscreen" value="2" summary="the surface is fullscreen">
++ <description summary="the surface is fullscreen">
++ The surface is fullscreen. The window geometry specified in the configure
++ event must be obeyed by the client.
++ </description>
++ </entry>
++ <entry name="resizing" value="3" summary="the surface is being resized">
++ <description summary="the surface is being resized">
++ The surface is being resized. The window geometry specified in the
++ configure event is a maximum; the client cannot resize beyond it.
++ Clients that have aspect ratio or cell sizing configuration can use
++ a smaller size, however.
++ </description>
++ </entry>
++ <entry name="activated" value="4" summary="the surface is now activated">
++ <description summary="the surface is now activated">
++ Client window decorations should be painted as if the window is
++ active. Do not assume this means that the window actually has
++ keyboard or pointer focus.
++ </description>
++ </entry>
++ </enum>
++
++ <request name="set_max_size">
++ <description summary="set the maximum size">
++ Set a maximum size for the window.
++
++ The client can specify a maximum size so that the compositor does
++ not try to configure the window beyond this size.
++
++ The width and height arguments are in window geometry coordinates.
++ See xdg_surface.set_window_geometry.
++
++ Values set in this way are double-buffered. They will get applied
++ on the next commit.
++
++ The compositor can use this information to allow or disallow
++ different states like maximize or fullscreen and draw accurate
++ animations.
++
++ Similarly, a tiling window manager may use this information to
++ place and resize client windows in a more effective way.
++
++ The client should not rely on the compositor to obey the maximum
++ size. The compositor may decide to ignore the values set by the
++ client and request a larger size.
++
++ If never set, or a value of zero in the request, means that the
++ client has no expected maximum size in the given dimension.
++ As a result, a client wishing to reset the maximum size
++ to an unspecified state can use zero for width and height in the
++ request.
++
++ Requesting a maximum size to be smaller than the minimum size of
++ a surface is illegal and will result in a protocol error.
++
++ The width and height must be greater than or equal to zero. Using
++ strictly negative values for width and height will result in a
++ protocol error.
++ </description>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ </request>
++
++ <request name="set_min_size">
++ <description summary="set the minimum size">
++ Set a minimum size for the window.
++
++ The client can specify a minimum size so that the compositor does
++ not try to configure the window below this size.
++
++ The width and height arguments are in window geometry coordinates.
++ See xdg_surface.set_window_geometry.
++
++ Values set in this way are double-buffered. They will get applied
++ on the next commit.
++
++ The compositor can use this information to allow or disallow
++ different states like maximize or fullscreen and draw accurate
++ animations.
++
++ Similarly, a tiling window manager may use this information to
++ place and resize client windows in a more effective way.
++
++ The client should not rely on the compositor to obey the minimum
++ size. The compositor may decide to ignore the values set by the
++ client and request a smaller size.
++
++ If never set, or a value of zero in the request, means that the
++ client has no expected minimum size in the given dimension.
++ As a result, a client wishing to reset the minimum size
++ to an unspecified state can use zero for width and height in the
++ request.
++
++ Requesting a minimum size to be larger than the maximum size of
++ a surface is illegal and will result in a protocol error.
++
++ The width and height must be greater than or equal to zero. Using
++ strictly negative values for width and height will result in a
++ protocol error.
++ </description>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ </request>
++
++ <request name="set_maximized">
++ <description summary="maximize the window">
++ Maximize the surface.
++
++ After requesting that the surface should be maximized, the compositor
++ will respond by emitting a configure event with the "maximized" state
++ and the required window geometry. The client should then update its
++ content, drawing it in a maximized state, i.e. without shadow or other
++ decoration outside of the window geometry. The client must also
++ acknowledge the configure when committing the new content (see
++ ack_configure).
++
++ It is up to the compositor to decide how and where to maximize the
++ surface, for example which output and what region of the screen should
++ be used.
++
++ If the surface was already maximized, the compositor will still emit
++ a configure event with the "maximized" state.
++ </description>
++ </request>
++
++ <request name="unset_maximized">
++ <description summary="unmaximize the window">
++ Unmaximize the surface.
++
++ After requesting that the surface should be unmaximized, the compositor
++ will respond by emitting a configure event without the "maximized"
++ state. If available, the compositor will include the window geometry
++ dimensions the window had prior to being maximized in the configure
++ request. The client must then update its content, drawing it in a
++ regular state, i.e. potentially with shadow, etc. The client must also
++ acknowledge the configure when committing the new content (see
++ ack_configure).
++
++ It is up to the compositor to position the surface after it was
++ unmaximized; usually the position the surface had before maximizing, if
++ applicable.
++
++ If the surface was already not maximized, the compositor will still
++ emit a configure event without the "maximized" state.
++ </description>
++ </request>
++
++ <request name="set_fullscreen">
++ <description summary="set the window as fullscreen on a monitor">
++ Make the surface fullscreen.
++
++ You can specify an output that you would prefer to be fullscreen.
++ If this value is NULL, it's up to the compositor to choose which
++ display will be used to map this surface.
++
++ If the surface doesn't cover the whole output, the compositor will
++ position the surface in the center of the output and compensate with
++ black borders filling the rest of the output.
++ </description>
++ <arg name="output" type="object" interface="wl_output" allow-null="true"/>
++ </request>
++ <request name="unset_fullscreen" />
++
++ <request name="set_minimized">
++ <description summary="set the window as minimized">
++ Request that the compositor minimize your surface. There is no
++ way to know if the surface is currently minimized, nor is there
++ any way to unset minimization on this surface.
++
++ If you are looking to throttle redrawing when minimized, please
++ instead use the wl_surface.frame event for this, as this will
++ also work with live previews on windows in Alt-Tab, Expose or
++ similar compositor features.
++ </description>
++ </request>
++
++ <event name="configure">
++ <description summary="suggest a surface change">
++ This configure event asks the client to resize its toplevel surface or
++ to change its state. The configured state should not be applied
++ immediately. See xdg_surface.configure for details.
++
++ The width and height arguments specify a hint to the window
++ about how its surface should be resized in window geometry
++ coordinates. See set_window_geometry.
++
++ If the width or height arguments are zero, it means the client
++ should decide its own window dimension. This may happen when the
++ compositor needs to configure the state of the surface but doesn't
++ have any information about any previous or expected dimension.
++
++ The states listed in the event specify how the width/height
++ arguments should be interpreted, and possibly how it should be
++ drawn.
++
++ Clients must send an ack_configure in response to this event. See
++ xdg_surface.configure and xdg_surface.ack_configure for details.
++ </description>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ <arg name="states" type="array"/>
++ </event>
++
++ <event name="close">
++ <description summary="surface wants to be closed">
++ The close event is sent by the compositor when the user
++ wants the surface to be closed. This should be equivalent to
++ the user clicking the close button in client-side decorations,
++ if your application has any.
++
++ This is only a request that the user intends to close the
++ window. The client may choose to ignore this request, or show
++ a dialog to ask the user to save their data, etc.
++ </description>
++ </event>
++ </interface>
++
++ <interface name="zxdg_popup_v6" version="1">
++ <description summary="short-lived, popup surfaces for menus">
++ A popup surface is a short-lived, temporary surface. It can be used to
++ implement for example menus, popovers, tooltips and other similar user
++ interface concepts.
++
++ A popup can be made to take an explicit grab. See xdg_popup.grab for
++ details.
++
++ When the popup is dismissed, a popup_done event will be sent out, and at
++ the same time the surface will be unmapped. See the xdg_popup.popup_done
++ event for details.
++
++ Explicitly destroying the xdg_popup object will also dismiss the popup and
++ unmap the surface. Clients that want to dismiss the popup when another
++ surface of their own is clicked should dismiss the popup using the destroy
++ request.
++
++ The parent surface must have either the xdg_toplevel or xdg_popup surface
++ role.
++
++ A newly created xdg_popup will be stacked on top of all previously created
++ xdg_popup surfaces associated with the same xdg_toplevel.
++
++ The parent of an xdg_popup must be mapped (see the xdg_surface
++ description) before the xdg_popup itself.
++
++ The x and y arguments passed when creating the popup object specify
++ where the top left of the popup should be placed, relative to the
++ local surface coordinates of the parent surface. See
++ xdg_surface.get_popup. An xdg_popup must intersect with or be at least
++ partially adjacent to its parent surface.
++
++ The client must call wl_surface.commit on the corresponding wl_surface
++ for the xdg_popup state to take effect.
++ </description>
++
++ <enum name="error">
++ <entry name="invalid_grab" value="0"
++ summary="tried to grab after being mapped"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="remove xdg_popup interface">
++ This destroys the popup. Explicitly destroying the xdg_popup
++ object will also dismiss the popup, and unmap the surface.
++
++ If this xdg_popup is not the "topmost" popup, a protocol error
++ will be sent.
++ </description>
++ </request>
++
++ <request name="grab">
++ <description summary="make the popup take an explicit grab">
++ This request makes the created popup take an explicit grab. An explicit
++ grab will be dismissed when the user dismisses the popup, or when the
++ client destroys the xdg_popup. This can be done by the user clicking
++ outside the surface, using the keyboard, or even locking the screen
++ through closing the lid or a timeout.
++
++ If the compositor denies the grab, the popup will be immediately
++ dismissed.
++
++ This request must be used in response to some sort of user action like a
++ button press, key press, or touch down event. The serial number of the
++ event should be passed as 'serial'.
++
++ The parent of a grabbing popup must either be an xdg_toplevel surface or
++ another xdg_popup with an explicit grab. If the parent is another
++ xdg_popup it means that the popups are nested, with this popup now being
++ the topmost popup.
++
++ Nested popups must be destroyed in the reverse order they were created
++ in, e.g. the only popup you are allowed to destroy at all times is the
++ topmost one.
++
++ When compositors choose to dismiss a popup, they may dismiss every
++ nested grabbing popup as well. When a compositor dismisses popups, it
++ will follow the same dismissing order as required from the client.
++
++ The parent of a grabbing popup must either be another xdg_popup with an
++ active explicit grab, or an xdg_popup or xdg_toplevel, if there are no
++ explicit grabs already taken.
++
++ If the topmost grabbing popup is destroyed, the grab will be returned to
++ the parent of the popup, if that parent previously had an explicit grab.
++
++ If the parent is a grabbing popup which has already been dismissed, this
++ popup will be immediately dismissed. If the parent is a popup that did
++ not take an explicit grab, an error will be raised.
++
++ During a popup grab, the client owning the grab will receive pointer
++ and touch events for all their surfaces as normal (similar to an
++ "owner-events" grab in X11 parlance), while the top most grabbing popup
++ will always have keyboard focus.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat"
++ summary="the wl_seat of the user event"/>
++ <arg name="serial" type="uint" summary="the serial of the user event"/>
++ </request>
++
++ <event name="configure">
++ <description summary="configure the popup surface">
++ This event asks the popup surface to configure itself given the
++ configuration. The configured state should not be applied immediately.
++ See xdg_surface.configure for details.
++
++ The x and y arguments represent the position the popup was placed at
++ given the xdg_positioner rule, relative to the upper left corner of the
++ window geometry of the parent surface.
++ </description>
++ <arg name="x" type="int"
++ summary="x position relative to parent surface window geometry"/>
++ <arg name="y" type="int"
++ summary="y position relative to parent surface window geometry"/>
++ <arg name="width" type="int" summary="window geometry width"/>
++ <arg name="height" type="int" summary="window geometry height"/>
++ </event>
++
++ <event name="popup_done">
++ <description summary="popup interaction is done">
++ The popup_done event is sent out when a popup is dismissed by the
++ compositor. The client should destroy the xdg_popup object at this
++ point.
++ </description>
++ </event>
++
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++Xwayland keyboard grabbing protocol
++
++Maintainers:
++Olivier Fourdan <ofourdan@redhat.com>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xwayland_keyboard_grab_unstable_v1">
++
++ <copyright>
++ Copyright © 2017 Red Hat Inc.
++
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </copyright>
++
++ <description summary="Protocol for grabbing the keyboard from Xwayland">
++ This protocol is application-specific to meet the needs of the X11
++ protocol through Xwayland. It provides a way for Xwayland to request
++ all keyboard events to be forwarded to a surface even when the
++ surface does not have keyboard focus.
++
++ In the X11 protocol, a client may request an "active grab" on the
++ keyboard. On success, all key events are reported only to the
++ grabbing X11 client. For details, see XGrabKeyboard(3).
++
++ The core Wayland protocol does not have a notion of an active
++ keyboard grab. When running in Xwayland, X11 applications may
++ acquire an active grab inside Xwayland but that cannot be translated
++ to the Wayland compositor who may set the input focus to some other
++ surface. In doing so, it breaks the X11 client assumption that all
++ key events are reported to the grabbing client.
++
++ This protocol specifies a way for Xwayland to request all keyboard
++ be directed to the given surface. The protocol does not guarantee
++ that the compositor will honor this request and it does not
++ prescribe user interfaces on how to handle the respond. For example,
++ a compositor may inform the user that all key events are now
++ forwarded to the given client surface, or it may ask the user for
++ permission to do so.
++
++ Compositors are required to restrict access to this application
++ specific protocol to Xwayland alone.
++
++ Warning! The protocol described in this file is experimental and
++ backward incompatible changes may be made. Backward compatible
++ changes may be added together with the corresponding interface
++ version bump.
++ Backward incompatible changes are done by bumping the version
++ number in the protocol and interface names and resetting the
++ interface version. Once the protocol is to be declared stable,
++ the 'z' prefix and the version number in the protocol and
++ interface names are removed and the interface version number is
++ reset.
++ </description>
++
++ <interface name="zwp_xwayland_keyboard_grab_manager_v1" version="1">
++ <description summary="context object for keyboard grab manager">
++ A global interface used for grabbing the keyboard.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the keyboard grab manager">
++ Destroy the keyboard grab manager.
++ </description>
++ </request>
++
++ <request name="grab_keyboard">
++ <description summary="grab the keyboard to a surface">
++ The grab_keyboard request asks for a grab of the keyboard, forcing
++ the keyboard focus for the given seat upon the given surface.
++
++ The protocol provides no guarantee that the grab is ever satisfied,
++ and does not require the compositor to send an error if the grab
++ cannot ever be satisfied. It is thus possible to request a keyboard
++ grab that will never be effective.
++
++ The protocol:
++
++ * does not guarantee that the grab itself is applied for a surface,
++ the grab request may be silently ignored by the compositor,
++ * does not guarantee that any events are sent to this client even
++ if the grab is applied to a surface,
++ * does not guarantee that events sent to this client are exhaustive,
++ a compositor may filter some events for its own consumption,
++ * does not guarantee that events sent to this client are continuous,
++ a compositor may change and reroute keyboard events while the grab
++ is nominally active.
++ </description>
++
++ <arg name="id" type="new_id" interface="zwp_xwayland_keyboard_grab_v1"/>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="surface to report keyboard events to"/>
++ <arg name="seat" type="object" interface="wl_seat"
++ summary="the seat for which the keyboard should be grabbed"/>
++ </request>
++ </interface>
++
++ <interface name="zwp_xwayland_keyboard_grab_v1" version="1">
++ <description summary="interface for grabbing the keyboard">
++ A global interface used for grabbing the keyboard.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the grabbed keyboard object">
++ Destroy the grabbed keyboard object. If applicable, the compositor
++ will ungrab the keyboard.
++ </description>
++ </request>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++pkgdatadir=@abs_top_srcdir@
++
++Name: Wayland Protocols
++Description: Wayland protocol files (not installed)
++Version: @WAYLAND_PROTOCOLS_VERSION@
--- /dev/null
--- /dev/null
++prefix=@prefix@
++datarootdir=@datarootdir@
++pkgdatadir=${pc_sysrootdir}${datarootdir}/@PACKAGE@
++
++Name: Wayland Protocols
++Description: Wayland protocol files
++Version: @WAYLAND_PROTOCOLS_VERSION@
--- /dev/null
--- /dev/null
++root = true
++
++[*]
++charset = utf-8
++end_of_line = lf
++trim_trailing_whitespace = true
++insert_final_newline = true
++indent_style = tab
++indent_size = 8
++max_line_length = 80
++
++[*.xml]
++indent_style = tab
++indent_size = 2
++tab_width = 8
++
++[*.py]
++indent_style = space
++indent_size = 4
++
++[*.yml]
++indent_style = space
++indent_size = 2
++max_line_length = off
--- /dev/null
--- /dev/null
++*.announce
++*.sig
++*.swp
++*.log
++*.tar.xz
++*~
++cscope.out
++ctags
--- /dev/null
--- /dev/null
++# This file uses the freedesktop ci-templates to build Wayland and run our
++# tests in CI.
++#
++# ci-templates uses a multi-stage build process. First, the base container
++# image is built which contains the core distribution, the toolchain, and
++# all our build dependencies. This container is aggressively cached; if a
++# container image matching $FDO_DISTRIBUTION_TAG is found in either the
++# upstream repo (wayland/weston) or the user's downstream repo, it is
++# reused for the build. This gives us predictability of build and far
++# quicker runtimes, however it means that any changes to the base container
++# must also change $FDO_DISTRIBUTION_TAG. When changing this, please use
++# the current date as well as a unique build identifier.
++#
++# After the container is either rebuilt (tag mismatch) or reused (tag
++# previously used), the build stage executes within this container.
++#
++# The final stage is used to expose documentation and coverage information,
++# including publishing documentation to the public site when built on the
++# main branch.
++#
++# Apart from the 'variables', 'include', and 'stages' top-level anchors,
++# everything not beginning with a dot ('.') is the name of a job which will
++# be executed as part of CI, unless the rules specify that it should not be
++# run.
++#
++# Variables prefixed with CI_ are generally provided by GitLab itself;
++# variables prefixed with FDO_ and templates prefixed by .fdo are provided
++# by the ci-templates.
++#
++# For more information on GitLab CI, including the YAML syntax, see:
++# https://docs.gitlab.com/ee/ci/yaml/README.html
++#
++# Note that freedesktop.org uses the 'Community Edition' of GitLab, so features
++# marked as 'premium' or 'ultimate' are not available to us.
++#
++# For more information on ci-templates, see:
++# - documentation at https://freedesktop.pages.freedesktop.org/ci-templates/
++# - repo at https://gitlab.freedesktop.org/freedesktop/ci-templates/
++
++# Here we use a fixed ref in order to isolate ourselves from ci-templates
++# API changes. If you need new features from ci-templates you must bump
++# this to the current SHA you require from the ci-templates repo, however
++# be aware that you may need to account for API changes when doing so.
++.templates_sha: &template_sha 567700e483aabed992d0a4fea84994a0472deff6 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
++
++include:
++ - project: 'freedesktop/ci-templates'
++ ref: *template_sha
++ file:
++ - '/templates/debian.yml'
++ - '/templates/freebsd.yml'
++ - '/templates/ci-fairy.yml'
++
++variables:
++ FDO_UPSTREAM_REPO: wayland/wayland
++ FDO_REPO_SUFFIX: "$BUILD_OS/$BUILD_ARCH"
++
++
++# Define the build stages. These are used for UI grouping as well as
++# dependencies.
++stages:
++ - "Merge request checks"
++ - "Base container"
++ - "Build and test"
++ - "Other build configurations"
++
++.ci-rules:
++ rules:
++ - when: on_success
++
++# Base variables used for anything using a Debian environment
++.os-debian:
++ variables:
++ BUILD_OS: debian
++ FDO_DISTRIBUTION_VERSION: buster
++ FDO_DISTRIBUTION_PACKAGES: 'build-essential pkg-config libexpat1-dev libffi-dev libxml2-dev doxygen graphviz xmlto xsltproc docbook-xsl python3-pip python3-setuptools ninja-build'
++ FDO_DISTRIBUTION_EXEC: 'pip3 install meson==0.56.0'
++ # bump this tag every time you change something which requires rebuilding the
++ # base image
++ FDO_DISTRIBUTION_TAG: "2022-02-05.0"
++
++.debian-x86_64:
++ extends:
++ - .os-debian
++ variables:
++ BUILD_ARCH: "x86-64"
++
++.debian-aarch64:
++ extends:
++ - .os-debian
++ variables:
++ BUILD_ARCH: "aarch64"
++
++.debian-armv7:
++ extends:
++ - .os-debian
++ variables:
++ BUILD_ARCH: "armv7"
++
++
++# Does not inherit .ci-rules as we only want it to run in MR context.
++check-commit:
++ extends:
++ - .fdo.ci-fairy
++ stage: "Merge request checks"
++ rules:
++ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
++ when: always
++ - when: never
++ script:
++ - ci-fairy check-commits --signed-off-by --junit-xml=results.xml
++ variables:
++ GIT_DEPTH: 100
++ artifacts:
++ reports:
++ junit: results.xml
++
++
++# Build our base container image, which contains the core distribution, the
++# toolchain, and all our build dependencies. This will be reused in the build
++# stage.
++x86_64-debian-container_prep:
++ extends:
++ - .ci-rules
++ - .debian-x86_64
++ - .fdo.container-build@debian
++ stage: "Base container"
++ variables:
++ GIT_STRATEGY: none
++
++aarch64-debian-container_prep:
++ extends:
++ - .ci-rules
++ - .debian-aarch64
++ - .fdo.container-build@debian
++ tags:
++ - aarch64
++ stage: "Base container"
++ variables:
++ GIT_STRATEGY: none
++
++armv7-debian-container_prep:
++ extends:
++ - .ci-rules
++ - .debian-armv7
++ - .fdo.container-build@debian
++ tags:
++ - aarch64
++ stage: "Base container"
++ variables:
++ GIT_STRATEGY: none
++ FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
++
++
++# Core build environment.
++.build-env:
++ variables:
++ MESON_BUILD_TYPE: "-Dbuildtype=debug -Doptimization=0 -Db_sanitize=address,undefined"
++ before_script:
++ - export BUILD_ID="wayland-$CI_JOB_NAME"
++ - export PREFIX="${CI_PROJECT_DIR}/prefix-${BUILD_ID}"
++ - export BUILDDIR="${CI_PROJECT_DIR}/build-${BUILD_ID}"
++ - mkdir "$BUILDDIR" "$PREFIX"
++
++
++# Build variants to be stacked on as required.
++.build-release:
++ stage: "Other build configurations"
++ variables:
++ MESON_BUILD_TYPE: "-Dbuildtype=release"
++
++
++# OS/architecture-specific variants
++.build-env-debian-x86_64:
++ extends:
++ - .fdo.suffixed-image@debian
++ - .debian-x86_64
++ - .build-env
++ needs:
++ - job: x86_64-debian-container_prep
++ artifacts: false
++
++.build-env-debian-aarch64:
++ extends:
++ - .fdo.suffixed-image@debian
++ - .debian-aarch64
++ - .build-env
++ variables:
++ # At least with the versions we have, the LSan runtime makes fork unusably
++ # slow on AArch64, which is bad news since the test suite decides to fork
++ # for every single subtest. For now, in order to get AArch64 builds and
++ # tests into CI, just assume that we're not going to leak any more on
++ # AArch64 than we would on ARMv7 or x86-64.
++ ASAN_OPTIONS: "detect_leaks=0"
++ tags:
++ - aarch64
++ needs:
++ - job: aarch64-debian-container_prep
++ artifacts: false
++
++.build-env-debian-armv7:
++ extends:
++ - .fdo.suffixed-image@debian
++ - .debian-armv7
++ - .build-env
++ tags:
++ - aarch64
++ needs:
++ - job: armv7-debian-container_prep
++ artifacts: false
++
++
++# Full build and test.
++.do-build:
++ extends:
++ - .ci-rules
++ stage: "Build and test"
++ script:
++ - cd "$BUILDDIR"
++ - meson --prefix="$PREFIX" -Dicon_directory=/usr/share/X11/icons -Dwerror=true ${MESON_BUILD_TYPE} ..
++ - ninja -k0 -j${FDO_CI_CONCURRENT:-4}
++ - meson test --num-processes ${FDO_CI_CONCURRENT:-4}
++ - ninja clean
++ artifacts:
++ name: wayland-$CI_JOB_NAME
++ when: always
++ paths:
++ - build-*/meson-logs
++ - prefix-*
++ reports:
++ junit: build-*/meson-logs/testlog.junit.xml
++
++# Full build and test.
++.do-build-qemu:
++ extends:
++ - .ci-rules
++ stage: "Build and test"
++ script:
++ # Start the VM and copy our workspace to the VM
++ - /app/vmctl start
++ - scp -r $PWD "vm:"
++ # The `set +e is needed to ensure that we always copy the meson logs back to
++ # the workspace to see details about the failed tests.
++ - |
++ set +e
++ /app/vmctl exec "pkg info; cd $CI_PROJECT_NAME ; meson $BUILDDIR --prefix=$PREFIX $MESON_BUILD_TYPE $MESON_ARGS && ninja -C $BUILDDIR -j${FDO_CI_CONCURRENT:-4}"
++ /app/vmctl exec "meson test --print-errorlogs -C $BUILDDIR --num-processes ${FDO_CI_CONCURRENT:-4}" && touch .tests-successful
++ set -ex
++ scp -r vm:$BUILDDIR/meson-logs .
++ /app/vmctl exec "ninja -C $BUILDDIR install"
++ mkdir -p $PREFIX && scp -r vm:$PREFIX/ $PREFIX/
++ # Finally, shut down the VM.
++ - /app/vmctl stop
++ - test -f .tests-successful || exit 1
++ artifacts:
++ name: wayland-$CI_JOB_NAME
++ when: always
++ paths:
++ - meson-logs
++ - prefix-*
++ reports:
++ junit: meson-logs/testlog.junit.xml
++
++# Full build and test.
++x86_64-debian-build:
++ extends:
++ - .build-env-debian-x86_64
++ - .do-build
++
++x86_64-release-debian-build:
++ extends:
++ - .build-env-debian-x86_64
++ - .do-build
++ - .build-release
++
++aarch64-debian-build:
++ extends:
++ - .build-env-debian-aarch64
++ - .do-build
++
++aarch64-release-debian-build:
++ extends:
++ - .build-env-debian-aarch64
++ - .do-build
++ - .build-release
++
++armv7-debian-build:
++ extends:
++ - .build-env-debian-armv7
++ - .do-build
++
++armv7-release-debian-build:
++ extends:
++ - .build-env-debian-armv7
++ - .do-build
++ - .build-release
++
++# Base variables used for anything using a FreeBSD environment
++.os-freebsd:
++ variables:
++ BUILD_OS: freebsd
++ FDO_DISTRIBUTION_VERSION: "13.0"
++ FDO_DISTRIBUTION_PACKAGES: 'libxslt meson ninja pkgconf expat libffi libepoll-shim libxml2'
++ # bump this tag every time you change something which requires rebuilding the
++ # base image
++ FDO_DISTRIBUTION_TAG: "2021-08-05.0"
++ # Don't build documentation since installing the required tools massively
++ # increases the VM image (and therefore container) size.
++ MESON_ARGS: "-Ddocumentation=false"
++
++.freebsd-x86_64:
++ extends:
++ - .os-freebsd
++ variables:
++ BUILD_ARCH: "x86_64"
++
++x86_64-freebsd-container_prep:
++ extends:
++ - .ci-rules
++ - .freebsd-x86_64
++ - .fdo.qemu-build@freebsd@x86_64
++ stage: "Base container"
++ variables:
++ GIT_STRATEGY: none
++
++.build-env-freebsd-x86_64:
++ variables:
++ # Compiling with ASan+UBSan appears to trigger an infinite loop in the
++ # compiler shipped with FreeBSD 13.0, so we only use UBSan here.
++ # Additionally, sanitizers can't be used with b_lundef on FreeBSD.
++ MESON_BUILD_TYPE: "-Dbuildtype=debug -Db_sanitize=undefined -Db_lundef=false"
++ extends:
++ - .fdo.suffixed-image@freebsd
++ - .freebsd-x86_64
++ - .build-env
++ needs:
++ - job: x86_64-freebsd-container_prep
++ artifacts: false
++
++# Full build and test.
++x86_64-freebsd-build:
++ extends:
++ - .build-env-freebsd-x86_64
++ - .do-build-qemu
++
++x86_64-release-freebsd-build:
++ extends:
++ - .build-env-freebsd-x86_64
++ - .do-build-qemu
++ - .build-release
--- /dev/null
--- /dev/null
++<!--
++This repository is for the Wayland protocol description and the libwayland IPC helper
++library only. Issues with Wayland during day-to-day usage are almost
++certainly a bug in your compositor and **not** a bug with in this
++repository.
++
++Please remove this comment before filing your bug.
++-->
--- /dev/null
--- /dev/null
++Contributing to Wayland
++=======================
++
++Sending patches
++---------------
++
++Patches should be sent via
++[GitLab merge requests](https://docs.gitlab.com/ce/gitlab-basics/add-merge-request.html).
++Wayland is
++[hosted on freedesktop.org's GitLab](https://gitlab.freedesktop.org/wayland/wayland/):
++in order to submit code, you should create an account on this GitLab instance,
++fork the core Wayland repository, push your changes to a branch in your new
++repository, and then submit these patches for review through a merge request.
++
++Wayland formerly accepted patches via `git-send-email`, sent to
++**wayland-devel@lists.freedesktop.org**; these were
++[tracked using Patchwork](https://patchwork.freedesktop.org/project/wayland/).
++Some old patches continue to be sent this way, and we may accept small new
++patches sent to the list, but please send all new patches through GitLab merge
++requests.
++
++
++Formatting and separating commits
++---------------------------------
++
++Unlike many projects using GitHub and GitLab, Wayland has a
++[linear, 'recipe' style history](http://www.bitsnbites.eu/git-history-work-log-vs-recipe/).
++This means that every commit should be small, digestible, stand-alone, and
++functional. Rather than a purely chronological commit history like this:
++
++ connection: plug a fd leak
++ plug another fd leak
++ connection: init fds to -1
++ close all fds
++ refactor checks into a new function
++ don't close fds we handed out
++
++we aim to have a clean history which only reflects the final state, broken up
++into functional groupings:
++
++ connection: Refactor out closure allocation
++ connection: Clear fds we shouldn't close to -1
++ connection: Make wl_closure_destroy() close fds of undispatched closures
++
++This ensures that the final patch series only contains the final state,
++without the changes and missteps taken along the development process.
++
++The first line of a commit message should contain a prefix indicating
++what part is affected by the patch followed by one sentence that
++describes the change. For examples:
++
++ protocol: Support scaled outputs and surfaces
++
++and
++
++ doc: generate server documentation from XML too
++
++If in doubt what prefix to use, look at other commits that change the
++same file(s) as the patch being sent.
++
++The body of the commit message should describe what the patch changes
++and why, and also note any particular side effects. This shouldn't be
++empty on most of the cases. It shouldn't take a lot of effort to write
++a commit message for an obvious change, so an empty commit message
++body is only acceptable if the questions "What?" and "Why?" are already
++answered on the one-line summary.
++
++The lines of the commit message should have at most 76 characters, to
++cope with the way git log presents them.
++
++See [notes on commit messages] for a recommended reading on writing commit
++messages.
++
++Your patches should also include a Signed-off-by line with your name and
++email address. If you're not the patch's original author, you should
++also gather S-o-b's by them (and/or whomever gave the patch to you.) The
++significance of this is that it certifies that you created the patch,
++that it was created under an appropriate open source license, or
++provided to you under those terms. This lets us indicate a chain of
++responsibility for the copyright status of the code.
++
++We won't reject patches that lack S-o-b, but it is strongly recommended.
++
++When you re-send patches, revised or not, it would be very good to document the
++changes compared to the previous revision in the commit message and/or the
++merge request. If you have already received Reviewed-by or Acked-by tags, you
++should evaluate whether they still apply and include them in the respective
++commit messages. Otherwise the tags may be lost, reviewers miss the credit they
++deserve, and the patches may cause redundant review effort.
++
++
++Tracking patches and following up
++---------------------------------
++
++Once submitted to GitLab, your patches will be reviewed by the Wayland
++development team on GitLab. Review may be entirely positive and result in your
++code landing instantly, in which case, great! You're done. However, we may ask
++you to make some revisions: fixing some bugs we've noticed, working to a
++slightly different design, or adding documentation and tests.
++
++If you do get asked to revise the patches, please bear in mind the notes above.
++You should use `git rebase -i` to make revisions, so that your patches follow
++the clear linear split documented above. Following that split makes it easier
++for reviewers to understand your work, and to verify that the code you're
++submitting is correct.
++
++A common request is to split single large patch into multiple patches. This can
++happen, for example, if when adding a new feature you notice a bug elsewhere
++which you need to fix to progress. Separating these changes into separate
++commits will allow us to verify and land the bugfix quickly, pushing part of
++your work for the good of everyone, whilst revision and discussion continues on
++the larger feature part. It also allows us to direct you towards reviewers who
++best understand the different areas you are working on.
++
++When you have made any requested changes, please rebase the commits, verify
++that they still individually look good, then force-push your new branch to
++GitLab. This will update the merge request and notify everyone subscribed to
++your merge request, so they can review it again.
++
++There are also
++[many GitLab CLI clients](https://about.gitlab.com/applications/#cli-clients),
++if you prefer to avoid the web interface. It may be difficult to follow review
++comments without using the web interface though, so we do recommend using this
++to go through the review process, even if you use other clients to track the
++list of available patches.
++
++
++Coding style
++------------
++
++You should follow the style of the file you're editing. In general, we
++try to follow the rules below.
++
++**Note: this file uses spaces due to markdown rendering issues for tabs.
++ Code must be implemented using tabs.**
++
++- indent with tabs, and a tab is always 8 characters wide
++- opening braces are on the same line as the if statement;
++- no braces in an if-body with just one statement;
++- if one of the branches of an if-else condition has braces, then the
++ other branch should also have braces;
++- there is always an empty line between variable declarations and the
++ code;
++
++```c
++static int
++my_function(void)
++{
++ int a = 0;
++
++ if (a)
++ b();
++ else
++ c();
++
++ if (a) {
++ b();
++ c();
++ } else {
++ d();
++ }
++}
++```
++
++- lines should be less than 80 characters wide;
++- when breaking lines with functions calls, the parameters are aligned
++ with the opening parentheses;
++- when assigning a variable with the result of a function call, if the
++ line would be longer we break it around the equal '=' sign if it makes
++ sense;
++
++```c
++ long_variable_name =
++ function_with_a_really_long_name(parameter1, parameter2,
++ parameter3, parameter4);
++
++ x = function_with_a_really_long_name(parameter1, parameter2,
++ parameter3, parameter4);
++```
++
++Conduct
++=======
++
++As a freedesktop.org project, Wayland follows the Contributor Covenant,
++found at:
++https://www.freedesktop.org/wiki/CodeOfConduct
++
++Please conduct yourself in a respectful and civilised manner when
++interacting with community members on mailing lists, IRC, or bug
++trackers. The community represents the project as a whole, and abusive
++or bullying behaviour is not tolerated by the project.
++
++
++Licensing
++=========
++
++Wayland is licensed with the intention to be usable anywhere X.org is.
++Originally, X.org was covered under the MIT X11 license, but changed to
++the MIT Expat license. Similarly, Wayland was covered initially as MIT
++X11 licensed, but changed to the MIT Expat license, following in X.org's
++footsteps. Other than wording, the two licenses are substantially the
++same, with the exception of a no-advertising clause in X11 not included
++in Expat.
++
++New source code files should specify the MIT Expat license in their
++boilerplate, as part of the copyright statement.
++
++
++Review
++======
++
++All patches, even trivial ones, require at least one positive review
++(Reviewed-by). Additionally, if no Reviewed-by's have been given by
++people with commit access, there needs to be at least one Acked-by from
++someone with commit access. A person with commit access is expected to be
++able to evaluate the patch with respect to the project scope and architecture.
++
++The below review guidelines are intended to be interpreted in spirit, not by
++the letter. There may be circumstances where some guidelines are better
++ignored. We rely very much on the judgement of reviewers and commit rights
++holders.
++
++During review, the following matters should be checked:
++
++- The commit message explains why the change is being made.
++
++- The code fits the project's scope.
++
++- The code license is the same MIT licence the project generally uses.
++
++- Stable ABI or API is not broken.
++
++- Stable ABI or API additions must be justified by actual use cases, not only
++by speculation. They must also be documented, and it is strongly recommended to
++include tests exercising the additions in the test suite.
++
++- The code fits the existing software architecture, e.g. no layering
++violations.
++
++- The code is correct and does not introduce new failures for existing users,
++does not add new corner-case bugs, and does not introduce new compiler
++warnings.
++
++- The patch does what it says in the commit message and changes nothing else.
++
++- The patch is a single logical change. If the commit message addresses
++multiple points, it is a hint that the commit might need splitting up.
++
++- A bug fix should target the underlying root cause instead of hiding symptoms.
++If a complete fix is not practical, partial fixes are acceptable if they come
++with code comments and filed Gitlab issues for the remaining bugs.
++
++- The bug root cause rule applies to external software components as well, e.g.
++do not work around kernel driver issues in userspace.
++
++- The test suite passes.
++
++- The code does not depend on API or ABI which has no working free open source
++implementation.
++
++- The code is not dead or untestable. E.g. if there are no free open source
++software users for it then it is effectively dead code.
++
++- The code is written to be easy to understand, or if code cannot be clear
++enough on its own there are code comments to explain it.
++
++- The code is minimal, i.e. prefer refactor and re-use when possible unless
++clarity suffers.
++
++- The code adheres to the style guidelines.
++
++- In a patch series, every intermediate step adheres to the above guidelines.
++
++
++Commit rights
++=============
++
++Commit rights will be granted to anyone who requests them and fulfills the
++below criteria:
++
++- Submitted some (10 as a rule of thumb) non-trivial (not just simple
++ spelling fixes and whitespace adjustment) patches that have been merged
++ already.
++
++- Are actively participating in public discussions about their work (on the
++ mailing list or IRC). This should not be interpreted as a requirement to
++ review other peoples patches but just make sure that patch submission isn't
++ one-way communication. Cross-review is still highly encouraged.
++
++- Will be regularly contributing further patches. This includes regular
++ contributors to other parts of the open source graphics stack who only
++ do the occasional development in this project.
++
++- Agrees to use their commit rights in accordance with the documented merge
++ criteria, tools, and processes.
++
++To apply for commit rights, create a new issue in gitlab for the respective
++project and give it the "accounts" label.
++
++Committers are encouraged to request their commit rights get removed when they
++no longer contribute to the project. Commit rights will be reinstated when they
++come back to the project.
++
++Maintainers and committers should encourage contributors to request commit
++rights, especially junior contributors tend to underestimate their skills.
++
++
++Stabilising for releases
++========================
++
++A release cycle ends with a stable release which also starts a new cycle and
++lifts any code freezes. Gradual code freezing towards a stable release starts
++with an alpha release. The release stages of a cycle are:
++
++- **Alpha release**:
++ Signified by version number #.#.91.
++ Major features must have landed before this. Major features include
++ invasive code motion and refactoring, high risk changes, and new stable
++ library ABI.
++
++- **Beta release**:
++ Signified by version number #.#.92.
++ Minor features must have landed before this. Minor features include all
++ new features that are not major, low risk changes, clean-ups, and
++ documentation. Stable ABI that was new in the alpha release can be removed
++ before a beta release if necessary.
++
++- **Release candidates (RC)**:
++ Signified by version number #.#.93 and up to #.#.99.
++ Bug fixes that are not release critical must have landed before this.
++ Release critical bug fixes can still be landed after this, but they may
++ call for another RC.
++
++- **Stable release**:
++ Signified by version number #.#.0.
++ Ideally no changes since the last RC.
++
++Mind that version #.#.90 is never released. It is used during development when
++no code freeze is in effect. Stable branches and point releases are not covered
++by the above.
++
++
++[git documentation]: http://git-scm.com/documentation
++[notes on commit messages]: http://who-t.blogspot.de/2009/12/on-commit-messages.html
--- /dev/null
--- /dev/null
++Copyright © 2008-2012 Kristian Høgsberg
++Copyright © 2010-2012 Intel Corporation
++Copyright © 2011 Benjamin Franzke
++Copyright © 2012 Collabora, Ltd.
++
++Permission is hereby granted, free of charge, to any person obtaining a
++copy of this software and associated documentation files (the "Software"),
++to deal in the Software without restriction, including without limitation
++the rights to use, copy, modify, merge, publish, distribute, sublicense,
++and/or sell copies of the Software, and to permit persons to whom the
++Software is furnished to do so, subject to the following conditions:
++
++The above copyright notice and this permission notice (including the next
++paragraph) shall be included in all copies or substantial portions of the
++Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++DEALINGS IN THE SOFTWARE.
++
++---
++
++The above is the version of the MIT "Expat" License used by X.org:
++
++ http://cgit.freedesktop.org/xorg/xserver/tree/COPYING
--- /dev/null
--- /dev/null
++What is Wayland?
++
++Wayland is a project to define a protocol for a compositor to talk to
++its clients as well as a library implementation of the protocol. The
++compositor can be a standalone display server running on Linux kernel
++modesetting and evdev input devices, an X application, or a wayland
++client itself. The clients can be traditional applications, X servers
++(rootless or fullscreen) or other display servers.
++
++The wayland protocol is essentially only about input handling and
++buffer management. The compositor receives input events and forwards
++them to the relevant client. The clients creates buffers and renders
++into them and notifies the compositor when it needs to redraw. The
++protocol also handles drag and drop, selections, window management and
++other interactions that must go through the compositor. However, the
++protocol does not handle rendering, which is one of the features that
++makes wayland so simple. All clients are expected to handle rendering
++themselves, typically through cairo or OpenGL.
++
++The weston compositor is a reference implementation of a wayland
++compositor and the weston repository also includes a few example
++clients.
++
++Building the wayland libraries is fairly simple, aside from libffi,
++they don't have many dependencies:
++
++ $ git clone https://gitlab.freedesktop.org/wayland/wayland
++ $ cd wayland
++ $ meson build/ --prefix=PREFIX
++ $ ninja -C build/ install
++
++where PREFIX is where you want to install the libraries. See
++https://wayland.freedesktop.org for more complete build instructions
++for wayland, weston, xwayland and various toolkits.
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Philipp Brüschweiler
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++/*
++ * This is a small, hacky tool to extract cursors from a .pcf file.
++ * The information about the file format has been gathered from
++ * http://fontforge.org/pcf-format.html
++ */
++
++#include <assert.h>
++#include <fcntl.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/mman.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++
++#define min(a, b) ((a) < (b) ? (a) : (b))
++#define max(a, b) ((a) > (b) ? (a) : (b))
++
++struct glyph {
++ char *name;
++ int16_t left_bearing, right_bearing, ascent, descent;
++
++ int16_t width, height;
++ int16_t hotx, hoty;
++
++ int32_t data_format;
++ char *data;
++};
++
++static struct {
++ int count;
++ struct glyph *glyphs;
++} extracted_font = {0, NULL};
++
++#define PCF_PROPERTIES (1<<0)
++#define PCF_ACCELERATORS (1<<1)
++#define PCF_METRICS (1<<2)
++#define PCF_BITMAPS (1<<3)
++#define PCF_INK_METRICS (1<<4)
++#define PCF_BDF_ENCODINGS (1<<5)
++#define PCF_SWIDTHS (1<<6)
++#define PCF_GLYPH_NAMES (1<<7)
++#define PCF_BDF_ACCELERATORS (1<<8)
++
++#define PCF_DEFAULT_FORMAT 0x00000000
++#define PCF_INKBOUNDS 0x00000200
++#define PCF_ACCEL_W_INKBOUNDS 0x00000100
++#define PCF_COMPRESSED_METRICS 0x00000100
++
++#define PCF_FORMAT_MASK 0xffffff00
++
++struct pcf_header {
++ char header[4];
++ int32_t table_count;
++ struct toc_entry {
++ int32_t type;
++ int32_t format;
++ int32_t size;
++ int32_t offset;
++ } tables[0];
++};
++
++struct compressed_metrics {
++ uint8_t left_sided_bearing;
++ uint8_t right_side_bearing;
++ uint8_t character_width;
++ uint8_t character_ascent;
++ uint8_t character_descent;
++};
++
++struct uncompressed_metrics {
++ int16_t left_sided_bearing;
++ int16_t right_side_bearing;
++ int16_t character_width;
++ int16_t character_ascent;
++ int16_t character_descent;
++ uint16_t character_attributes;
++};
++
++struct metrics {
++ int32_t format;
++ union {
++ struct {
++ int16_t count;
++ struct compressed_metrics compressed_metrics[0];
++ } compressed;
++ struct {
++ int32_t count;
++ struct uncompressed_metrics uncompressed_metrics[0];
++ } uncompressed;
++ };
++};
++
++struct glyph_names {
++ int32_t format;
++ int32_t glyph_count;
++ int32_t offsets[0];
++};
++
++struct bitmaps {
++ int32_t format;
++ int32_t glyph_count;
++ int32_t offsets[0];
++};
++
++static void
++handle_compressed_metrics(int32_t count, struct compressed_metrics *m)
++{
++ printf("metrics count: %d\n", count);
++ extracted_font.count = count;
++ extracted_font.glyphs = calloc(count, sizeof(struct glyph));
++
++ int i;
++ for (i = 0; i < count; ++i) {
++ struct glyph *glyph = &extracted_font.glyphs[i];
++ glyph->left_bearing =
++ ((int16_t) m[i].left_sided_bearing) - 0x80;
++ glyph->right_bearing =
++ ((int16_t) m[i].right_side_bearing) - 0x80;
++ glyph->width = ((int16_t) m[i].character_width) - 0x80;
++ glyph->ascent = ((int16_t) m[i].character_ascent) - 0x80;
++ glyph->descent = ((int16_t) m[i].character_descent) - 0x80;
++
++ /* computed stuff */
++ glyph->height = glyph->ascent + glyph->descent;
++
++ glyph->hotx = -glyph->left_bearing;
++ glyph->hoty = glyph->ascent;
++ }
++}
++
++static void
++handle_metrics(void *metricbuf)
++{
++ struct metrics *metrics = metricbuf;
++ printf("metric format: %x\n", metrics->format);
++
++ if ((metrics->format & PCF_FORMAT_MASK) == PCF_DEFAULT_FORMAT) {
++ printf("todo...\n");
++ } else if ((metrics->format & PCF_FORMAT_MASK) ==
++ PCF_COMPRESSED_METRICS) {
++ handle_compressed_metrics(
++ metrics->compressed.count,
++ &metrics->compressed.compressed_metrics[0]);
++ } else {
++ printf("incompatible format\n");
++ abort();
++ }
++}
++
++static void
++handle_glyph_names(struct glyph_names *names)
++{
++ printf("glyph count %d\n", names->glyph_count);
++
++ if (names->glyph_count != extracted_font.count) {
++ abort();
++ }
++
++ printf("glyph names format %x\n", names->format);
++
++ void *names_start = ((void*) names) + sizeof(struct glyph_names)
++ + (names->glyph_count + 1) * sizeof(int32_t);
++
++ int i;
++ for (i = 0; i < names->glyph_count; ++i) {
++ int32_t start = names->offsets[i];
++ int32_t end = names->offsets[i+1];
++ char *name = names_start + start;
++ extracted_font.glyphs[i].name = calloc(1, end - start + 1);
++ memcpy(extracted_font.glyphs[i].name, name, end - start);
++ }
++}
++
++static void
++handle_bitmaps(struct bitmaps *bitmaps)
++{
++ printf("bitmaps count %d\n", bitmaps->glyph_count);
++
++ if (bitmaps->glyph_count != extracted_font.count) {
++ abort();
++ }
++
++ printf("format %x\n", bitmaps->format);
++
++ if (bitmaps->format != 2) {
++ printf("format not yet supported\n");
++ abort();
++ }
++
++ void *bitmaps_start = ((void*) bitmaps) + sizeof(struct bitmaps)
++ + (bitmaps->glyph_count + 4) * sizeof(int32_t);
++
++ int i;
++ for (i = 0; i < bitmaps->glyph_count; ++i) {
++ int32_t offset = bitmaps->offsets[i];
++ struct glyph *glyph = &extracted_font.glyphs[i];
++ glyph->data_format = bitmaps->format;
++
++ glyph->data = bitmaps_start + offset;
++ }
++}
++
++static void
++handle_pcf(void *fontbuf)
++{
++ struct pcf_header *header = fontbuf;
++ printf("tablecount %d\n", header->table_count);
++
++ int i;
++ for (i = 0; i < header->table_count; ++i) {
++ struct toc_entry *entry = &header->tables[i];
++ printf("type: %d\n", entry->type);
++ if (entry->type == PCF_METRICS) {
++ handle_metrics(fontbuf + entry->offset);
++ } else if (entry->type == PCF_GLYPH_NAMES) {
++ handle_glyph_names(fontbuf + entry->offset);
++ } else if (entry->type == PCF_BITMAPS) {
++ handle_bitmaps(fontbuf + entry->offset);
++ }
++ }
++}
++
++static char
++get_glyph_pixel(struct glyph *glyph, int x, int y)
++{
++ int absx = glyph->hotx + x;
++ int absy = glyph->hoty + y;
++
++ if (absx < 0 || absx >= glyph->width ||
++ absy < 0 || absy >= glyph->height)
++ return 0;
++
++ int stride = (glyph->width + 31) / 32 * 4;
++ unsigned char block = glyph->data[absy * stride + (absx/8)];
++ int idx = absx % 8;
++ return (block >> idx) & 1;
++}
++
++static struct {
++ uint32_t *data;
++ size_t capacity, size;
++} data_buffer;
++
++static void
++init_data_buffer()
++{
++ data_buffer.data = malloc(sizeof(uint32_t) * 10);
++ data_buffer.capacity = 10;
++ data_buffer.size = 0;
++}
++
++static void
++add_pixel(uint32_t pixel)
++{
++ if (data_buffer.size == data_buffer.capacity) {
++ data_buffer.capacity *= 2;
++ data_buffer.data =
++ realloc(data_buffer.data,
++ sizeof(uint32_t) * data_buffer.capacity);
++ }
++ data_buffer.data[data_buffer.size++] = pixel;
++}
++
++struct reconstructed_glyph {
++ int32_t width, height;
++ int32_t hotspot_x, hotspot_y;
++ size_t offset;
++ char *name;
++};
++
++static void
++reconstruct_glyph(struct glyph *cursor, struct glyph *mask, char *name,
++ struct reconstructed_glyph *glyph)
++{
++ int minx = min(-cursor->hotx, -mask->hotx);
++ int maxx = max(cursor->right_bearing, mask->right_bearing);
++
++ int miny = min(-cursor->hoty, -mask->hoty);
++ int maxy = max(cursor->height - cursor->hoty,
++ mask->height - mask->hoty);
++
++ int width = maxx - minx;
++ int height = maxy - miny;
++
++ glyph->name = strdup(name);
++ glyph->width = width;
++ glyph->height = height;
++ glyph->hotspot_x = -minx;
++ glyph->hotspot_y = -miny;
++ glyph->offset = data_buffer.size;
++
++ int x, y;
++ for (y = miny; y < maxy; ++y) {
++ for (x = minx; x < maxx; ++x) {
++ char alpha = get_glyph_pixel(mask, x, y);
++ if (alpha) {
++ char color = get_glyph_pixel(cursor, x, y);
++ if (color)
++ add_pixel(0xff000000);
++ else
++ add_pixel(0xffffffff);
++ } else {
++ add_pixel(0);
++ }
++ }
++ }
++}
++
++/*
++ * Originally from
++ * http://cgit.freedesktop.org/xorg/lib/libXfont/tree/src/builtins/fonts.c
++ * Changed to the MIT "Expat" style license for Wayland..
++ */
++static const char cursor_licence[] =
++ "/*\n"
++ "* Copyright 1999 SuSE, Inc.\n"
++ "*\n"
++ "* Permission is hereby granted, free of charge, to any person obtaining\n"
++ "* a copy of this software and associated documentation files (the\n"
++ "* \"Software\"), to deal in the Software without restriction, including\n"
++ "* without limitation the rights to use, copy, modify, merge, publish,\n"
++ "* distribute, sublicense, and/or sell copies of the Software, and to\n"
++ "* permit persons to whom the Software is furnished to do so, subject to\n"
++ "* the following conditions:\n"
++ "*\n"
++ "* The above copyright notice and this permission notice (including the\n"
++ "* next paragraph) shall be included in all copies or substantial\n"
++ "* portions of the Software.\n"
++ "*\n"
++ "* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n"
++ "* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n"
++ "* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n"
++ "* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n"
++ "* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n"
++ "* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n"
++ "* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n"
++ "* SOFTWARE.\n"
++ "*\n"
++ "* Author: Keith Packard, SuSE, Inc.\n"
++ "*/\n";
++
++static void
++write_output_file(struct reconstructed_glyph *glyphs, int n)
++{
++ int i, j, counter, size;
++ FILE *file = fopen("cursor-data.h", "w");
++ uint32_t *data;
++
++ fprintf(file, "%s\n", cursor_licence);
++
++ fprintf(file, "static uint32_t cursor_data[] = {\n\t");
++
++ counter = 0;
++ for (i = 0; i < n; ++i) {
++ data = data_buffer.data + glyphs[i].offset;
++ size = glyphs[i].width * glyphs[i].height;
++
++ for (j = 0; j < size; ++j) {
++ fprintf(file, "0x%08x, ", data[j]);
++ if (++counter % 6 == 0)
++ fprintf(file, "\n\t");
++ }
++ }
++ fprintf(file, "\n};\n\n");
++
++ fprintf(file,
++ "static struct {\n"
++ "\tchar *name;\n"
++ "\tint width, height;\n"
++ "\tint hotspot_x, hotspot_y;\n"
++ "\tsize_t offset;\n"
++ "} cursor_metadata[] = {\n");
++
++ for (i = 0; i < n; ++i)
++ fprintf(file, "\t{ \"%s\", %d, %d, %d, %d, %zu },\n",
++ glyphs[i].name,
++ glyphs[i].width, glyphs[i].height,
++ glyphs[i].hotspot_x, glyphs[i].hotspot_y,
++ glyphs[i].offset);
++
++ fprintf(file, "};");
++
++ fclose(file);
++}
++
++struct glyph *
++find_mask_glyph(char *name)
++{
++ const char mask[] = "_mask";
++ const int masklen = strlen(mask);
++
++ int len = strlen(name);
++ int i;
++ for (i = 0; i < extracted_font.count; ++i) {
++ struct glyph *g = &extracted_font.glyphs[i];
++ int l2 = strlen(g->name);
++ if ((l2 == len + masklen) &&
++ (memcmp(g->name, name, len) == 0) &&
++ (memcmp(g->name + len, mask, masklen) == 0)) {
++ return g;
++ }
++ }
++ return NULL;
++}
++
++static void
++output_all_cursors()
++{
++ int i, j;
++ struct reconstructed_glyph *glyphs =
++ malloc(sizeof(struct reconstructed_glyph) *
++ extracted_font.count/2);
++ j = 0;
++
++ for (i = 0; i < extracted_font.count; ++i) {
++ struct glyph *g = &extracted_font.glyphs[i];
++ if (strstr(g->name, "_mask"))
++ continue;
++
++ struct glyph *mask = find_mask_glyph(g->name);
++
++ reconstruct_glyph(g, mask, g->name, &glyphs[j]);
++ j++;
++ }
++
++ write_output_file(glyphs, extracted_font.count/2);
++}
++
++static void
++find_cursor_and_mask(const char *name,
++ struct glyph **cursor,
++ struct glyph **mask)
++{
++ int i;
++ char mask_name[100];
++ sprintf(mask_name, "%s_mask", name);
++
++ *cursor = *mask = NULL;
++
++ for (i = 0; i < extracted_font.count && (!*mask || !*cursor); ++i) {
++ struct glyph *g = &extracted_font.glyphs[i];
++ if (!strcmp(name, g->name))
++ *cursor = g;
++ else if (!strcmp(mask_name, g->name))
++ *mask = g;
++ }
++}
++
++static struct {
++ char *target_name, *source_name;
++} interesting_cursors[] = {
++ { "bottom_left_corner", "bottom_left_corner" },
++ { "bottom_right_corner", "bottom_right_corner" },
++ { "bottom_side", "bottom_side" },
++ { "grabbing", "fleur" },
++ { "left_ptr", "left_ptr" },
++ { "left_side", "left_side" },
++ { "right_side", "right_side" },
++ { "top_left_corner", "top_left_corner" },
++ { "top_right_corner", "top_right_corner" },
++ { "top_side", "top_side" },
++ { "xterm", "xterm" },
++ { "hand1", "hand1" },
++ { "watch", "watch" }
++};
++
++static void
++output_interesting_cursors()
++{
++ int i;
++ int n = sizeof(interesting_cursors) / sizeof(interesting_cursors[0]);
++ struct reconstructed_glyph *glyphs =
++ malloc(n * sizeof(*glyphs));
++
++ if (!glyphs) {
++ printf("reconstructed_glyph malloc failed\n");
++ abort();
++ }
++
++ for (i = 0; i < n; ++i) {
++ struct glyph *cursor, *mask;
++ find_cursor_and_mask(interesting_cursors[i].source_name,
++ &cursor, &mask);
++ if (!cursor) {
++ printf("no cursor for %s\n",
++ interesting_cursors[i].source_name);
++ abort();
++ }
++ if (!mask) {
++ printf("no mask for %s\n",
++ interesting_cursors[i].source_name);
++ abort();
++ }
++ reconstruct_glyph(cursor, mask,
++ interesting_cursors[i].target_name,
++ &glyphs[i]);
++ }
++
++ write_output_file(glyphs, n);
++}
++
++int main()
++{
++ const char filename[] = "cursor.pcf";
++
++ int fd = open(filename, O_RDONLY);
++ struct stat filestat;
++
++ fstat(fd, &filestat);
++
++ void *fontbuf = mmap(NULL, filestat.st_size, PROT_READ,
++ MAP_PRIVATE, fd, 0);
++
++ handle_pcf(fontbuf);
++
++ init_data_buffer();
++
++ //output_all_cursors();
++ output_interesting_cursors();
++}
--- /dev/null
--- /dev/null
++/*
++* Copyright 1999 SuSE, Inc.
++*
++* Permission is hereby granted, free of charge, to any person obtaining
++* a copy of this software and associated documentation files (the
++* "Software"), to deal in the Software without restriction, including
++* without limitation the rights to use, copy, modify, merge, publish,
++* distribute, sublicense, and/or sell copies of the Software, and to
++* permit persons to whom the Software is furnished to do so, subject to
++* the following conditions:
++*
++* The above copyright notice and this permission notice (including the
++* next paragraph) shall be included in all copies or substantial
++* portions of the Software.
++*
++* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++* SOFTWARE.
++*
++* Author: Keith Packard, SuSE, Inc.
++*/
++
++#include <stdint.h>
++
++static uint32_t cursor_data[] = {
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000,
++ 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0x00000000,
++ 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000,
++ 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++ 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++ 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff,
++ 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0xffffffff, 0x00000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0xff000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff,
++ 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++ 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++ 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000,
++};
++
++static struct cursor_metadata {
++ char *name;
++ int width, height;
++ int hotspot_x, hotspot_y;
++ size_t offset;
++} cursor_metadata[] = {
++ { "bottom_left_corner", 16, 16, 1, 14, 0 },
++ { "bottom_right_corner", 16, 16, 14, 14, 256 },
++ { "bottom_side", 15, 16, 7, 14, 512 },
++ { "grabbing", 16, 16, 8, 8, 752 },
++ { "left_ptr", 10, 16, 1, 1, 1008 },
++ { "left_side", 16, 15, 1, 7, 1168 },
++ { "right_side", 16, 15, 14, 7, 1408 },
++ { "top_left_corner", 16, 16, 1, 1, 1648 },
++ { "top_right_corner", 16, 16, 14, 1, 1904 },
++ { "top_side", 15, 16, 7, 1, 2160 },
++ { "xterm", 9, 16, 4, 8, 2400 },
++ { "hand1", 13, 16, 12, 0, 2544 },
++ { "watch", 16, 16, 15, 9, 2752 },
++};
--- /dev/null
--- /dev/null
++icondir = get_option('icon_directory')
++if icondir == ''
++ icondir = join_paths(get_option('prefix'), get_option('datadir'), 'icons')
++endif
++
++if wayland_version[0] != '1'
++ # The versioning used for the shared libraries assumes that the major
++ # version of Wayland as a whole will increase to 2 if and only if there
++ # is an ABI break, at which point we should probably bump the SONAME of
++ # all libraries to .so.2. For more details see
++ # https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/177
++ error('We probably need to bump the SONAME of libwayland-cursor')
++endif
++
++wayland_cursor = library(
++ 'wayland-cursor',
++ sources: [
++ 'wayland-cursor.c',
++ 'os-compatibility.c',
++ 'xcursor.c',
++ ],
++ # To avoid an unnecessary SONAME bump, wayland 1.x.y produces
++ # libwayland-cursor.so.0.x.y.
++ version: '.'.join(['0', wayland_version[1], wayland_version[2]]),
++ dependencies: [ wayland_client_dep ],
++ c_args: [ '-DICONDIR="@0@"'.format(icondir) ],
++ install: true,
++)
++
++install_headers('wayland-cursor.h')
++
++pkgconfig.generate(
++ name: 'Wayland Cursor',
++ description: 'Wayland cursor helper library',
++ version: meson.project_version(),
++ libraries: wayland_cursor,
++ filebase: 'wayland-cursor',
++)
++
++wayland_cursor_dep = declare_dependency(
++ link_with: wayland_cursor,
++ include_directories: [ root_inc, include_directories('.') ],
++)
++
++if meson.version().version_compare('>= 0.54.0')
++ meson.override_dependency('wayland-cursor', wayland_cursor_dep)
++endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++
++#include "config.h"
++
++#include <sys/types.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <signal.h>
++#include <string.h>
++#include <stdio.h>
++#include <stdlib.h>
++
++#ifdef HAVE_MEMFD_CREATE
++#include <sys/mman.h>
++#endif
++
++#include "os-compatibility.h"
++
++#ifndef HAVE_MKOSTEMP
++static int
++set_cloexec_or_close(int fd)
++{
++ long flags;
++
++ if (fd == -1)
++ return -1;
++
++ flags = fcntl(fd, F_GETFD);
++ if (flags == -1)
++ goto err;
++
++ if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
++ goto err;
++
++ return fd;
++
++err:
++ close(fd);
++ return -1;
++}
++#endif
++
++static int
++create_tmpfile_cloexec(char *tmpname)
++{
++ int fd;
++
++#ifdef HAVE_MKOSTEMP
++ fd = mkostemp(tmpname, O_CLOEXEC);
++ if (fd >= 0)
++ unlink(tmpname);
++#else
++ fd = mkstemp(tmpname);
++ if (fd >= 0) {
++ fd = set_cloexec_or_close(fd);
++ unlink(tmpname);
++ }
++#endif
++
++ return fd;
++}
++
++/*
++ * Create a new, unique, anonymous file of the given size, and
++ * return the file descriptor for it. The file descriptor is set
++ * CLOEXEC. The file is immediately suitable for mmap()'ing
++ * the given size at offset zero.
++ *
++ * The file should not have a permanent backing store like a disk,
++ * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
++ *
++ * The file name is deleted from the file system.
++ *
++ * The file is suitable for buffer sharing between processes by
++ * transmitting the file descriptor over Unix sockets using the
++ * SCM_RIGHTS methods.
++ *
++ * If the C library implements posix_fallocate(), it is used to
++ * guarantee that disk space is available for the file at the
++ * given size. If disk space is insufficient, errno is set to ENOSPC.
++ * If posix_fallocate() is not supported, program may receive
++ * SIGBUS on accessing mmap()'ed file contents instead.
++ *
++ * If the C library implements memfd_create(), it is used to create the
++ * file purely in memory, without any backing file name on the file
++ * system, and then sealing off the possibility of shrinking it. This
++ * can then be checked before accessing mmap()'ed file contents, to
++ * make sure SIGBUS can't happen. It also avoids requiring
++ * XDG_RUNTIME_DIR.
++ */
++int
++os_create_anonymous_file(off_t size)
++{
++ static const char template[] = "/wayland-cursor-shared-XXXXXX";
++ const char *path;
++ char *name;
++ size_t name_size;
++ int fd;
++
++#ifdef HAVE_MEMFD_CREATE
++ fd = memfd_create("wayland-cursor", MFD_CLOEXEC | MFD_ALLOW_SEALING);
++ if (fd >= 0) {
++ /* We can add this seal before calling posix_fallocate(), as
++ * the file is currently zero-sized anyway.
++ *
++ * There is also no need to check for the return value, we
++ * couldn't do anything with it anyway.
++ */
++ fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
++ } else
++#endif
++ {
++ path = getenv("XDG_RUNTIME_DIR");
++ if (!path || path[0] != '/') {
++ errno = ENOENT;
++ return -1;
++ }
++
++ name_size = strlen(path) + sizeof(template);
++ name = malloc(name_size);
++ if (!name)
++ return -1;
++
++ snprintf(name, name_size, "%s%s", path, template);
++
++ fd = create_tmpfile_cloexec(name);
++
++ free(name);
++
++ if (fd < 0)
++ return -1;
++ }
++
++ if (os_resize_anonymous_file(fd, size) < 0) {
++ close(fd);
++ return -1;
++ }
++
++ return fd;
++}
++
++int
++os_resize_anonymous_file(int fd, off_t size)
++{
++#ifdef HAVE_POSIX_FALLOCATE
++ sigset_t mask;
++ sigset_t old_mask;
++
++ /*
++ * posix_fallocate() might be interrupted, so we need to check
++ * for EINTR and retry in that case.
++ * However, in the presence of an alarm, the interrupt may trigger
++ * repeatedly and prevent a large posix_fallocate() to ever complete
++ * successfully, so we need to first block SIGALRM to prevent
++ * this.
++ */
++ sigemptyset(&mask);
++ sigaddset(&mask, SIGALRM);
++ sigprocmask(SIG_BLOCK, &mask, &old_mask);
++ /*
++ * Filesystems that do not support fallocate will return EINVAL or
++ * EOPNOTSUPP. In this case we need to fall back to ftruncate
++ */
++ do {
++ errno = posix_fallocate(fd, 0, size);
++ } while (errno == EINTR);
++ sigprocmask(SIG_SETMASK, &old_mask, NULL);
++ if (errno == 0)
++ return 0;
++ else if (errno != EINVAL && errno != EOPNOTSUPP)
++ return -1;
++#endif
++ if (ftruncate(fd, size) < 0)
++ return -1;
++
++ return 0;
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef OS_COMPATIBILITY_H
++#define OS_COMPATIBILITY_H
++
++#include <sys/types.h>
++
++int
++os_create_anonymous_file(off_t size);
++
++int
++os_resize_anonymous_file(int fd, off_t size);
++
++#endif /* OS_COMPATIBILITY_H */
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "config.h"
++#include "xcursor.h"
++#include "wayland-cursor.h"
++#include "wayland-client.h"
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/mman.h>
++#include <fcntl.h>
++#include <errno.h>
++
++#include "os-compatibility.h"
++
++#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
++
++struct shm_pool {
++ struct wl_shm_pool *pool;
++ int fd;
++ unsigned int size;
++ unsigned int used;
++ char *data;
++};
++
++static struct shm_pool *
++shm_pool_create(struct wl_shm *shm, int size)
++{
++ struct shm_pool *pool;
++
++ pool = malloc(sizeof *pool);
++ if (!pool)
++ return NULL;
++
++ pool->fd = os_create_anonymous_file(size);
++ if (pool->fd < 0)
++ goto err_free;
++
++ pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
++ pool->fd, 0);
++
++ if (pool->data == MAP_FAILED)
++ goto err_close;
++
++ pool->pool = wl_shm_create_pool(shm, pool->fd, size);
++ pool->size = size;
++ pool->used = 0;
++
++ return pool;
++
++err_close:
++ close(pool->fd);
++err_free:
++ free(pool);
++ return NULL;
++}
++
++static int
++shm_pool_resize(struct shm_pool *pool, int size)
++{
++ if (os_resize_anonymous_file(pool->fd, size) < 0)
++ return 0;
++
++ wl_shm_pool_resize(pool->pool, size);
++
++ munmap(pool->data, pool->size);
++
++ pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
++ pool->fd, 0);
++ if (pool->data == MAP_FAILED)
++ return 0;
++ pool->size = size;
++
++ return 1;
++}
++
++static int
++shm_pool_allocate(struct shm_pool *pool, int size)
++{
++ int offset;
++
++ if (pool->used + size > pool->size)
++ if (!shm_pool_resize(pool, 2 * pool->size + size))
++ return -1;
++
++ offset = pool->used;
++ pool->used += size;
++
++ return offset;
++}
++
++static void
++shm_pool_destroy(struct shm_pool *pool)
++{
++ munmap(pool->data, pool->size);
++ wl_shm_pool_destroy(pool->pool);
++ close(pool->fd);
++ free(pool);
++}
++
++
++struct wl_cursor_theme {
++ unsigned int cursor_count;
++ struct wl_cursor **cursors;
++ struct wl_shm *shm;
++ struct shm_pool *pool;
++ int size;
++};
++
++struct cursor_image {
++ struct wl_cursor_image image;
++ struct wl_cursor_theme *theme;
++ struct wl_buffer *buffer;
++ int offset; /* data offset of this image in the shm pool */
++};
++
++struct cursor {
++ struct wl_cursor cursor;
++ uint32_t total_delay; /* length of the animation in ms */
++};
++
++/** Get an shm buffer for a cursor image
++ *
++ * \param image The cursor image
++ * \return An shm buffer for the cursor image. The user should not destroy
++ * the returned buffer.
++ */
++WL_EXPORT struct wl_buffer *
++wl_cursor_image_get_buffer(struct wl_cursor_image *_img)
++{
++ struct cursor_image *image = (struct cursor_image *) _img;
++ struct wl_cursor_theme *theme = image->theme;
++
++ if (!image->buffer) {
++ image->buffer =
++ wl_shm_pool_create_buffer(theme->pool->pool,
++ image->offset,
++ _img->width, _img->height,
++ _img->width * 4,
++ WL_SHM_FORMAT_ARGB8888);
++ };
++
++ return image->buffer;
++}
++
++static void
++wl_cursor_image_destroy(struct wl_cursor_image *_img)
++{
++ struct cursor_image *image = (struct cursor_image *) _img;
++
++ if (image->buffer)
++ wl_buffer_destroy(image->buffer);
++
++ free(image);
++}
++
++static void
++wl_cursor_destroy(struct wl_cursor *cursor)
++{
++ unsigned int i;
++
++ for (i = 0; i < cursor->image_count; i++)
++ wl_cursor_image_destroy(cursor->images[i]);
++
++ free(cursor->images);
++ free(cursor->name);
++ free(cursor);
++}
++
++#include "cursor-data.h"
++
++static struct wl_cursor *
++wl_cursor_create_from_data(struct cursor_metadata *metadata,
++ struct wl_cursor_theme *theme)
++{
++ struct cursor *cursor;
++ struct cursor_image *image;
++ int size;
++
++ cursor = malloc(sizeof *cursor);
++ if (!cursor)
++ return NULL;
++
++ cursor->cursor.image_count = 1;
++ cursor->cursor.images = malloc(sizeof *cursor->cursor.images);
++ if (!cursor->cursor.images)
++ goto err_free_cursor;
++
++ cursor->cursor.name = strdup(metadata->name);
++ cursor->total_delay = 0;
++
++ image = malloc(sizeof *image);
++ if (!image)
++ goto err_free_images;
++
++ cursor->cursor.images[0] = (struct wl_cursor_image *) image;
++ image->theme = theme;
++ image->buffer = NULL;
++ image->image.width = metadata->width;
++ image->image.height = metadata->height;
++ image->image.hotspot_x = metadata->hotspot_x;
++ image->image.hotspot_y = metadata->hotspot_y;
++ image->image.delay = 0;
++
++ size = metadata->width * metadata->height * sizeof(uint32_t);
++ image->offset = shm_pool_allocate(theme->pool, size);
++
++ if (image->offset < 0)
++ goto err_free_image;
++
++ memcpy(theme->pool->data + image->offset,
++ cursor_data + metadata->offset, size);
++
++ return &cursor->cursor;
++
++err_free_image:
++ free(image);
++
++err_free_images:
++ free(cursor->cursor.name);
++ free(cursor->cursor.images);
++
++err_free_cursor:
++ free(cursor);
++ return NULL;
++}
++
++static void
++load_fallback_theme(struct wl_cursor_theme *theme)
++{
++ uint32_t i;
++
++ theme->cursor_count = ARRAY_LENGTH(cursor_metadata);
++ theme->cursors = malloc(theme->cursor_count * sizeof(*theme->cursors));
++
++ if (theme->cursors == NULL) {
++ theme->cursor_count = 0;
++ return;
++ }
++
++ for (i = 0; i < theme->cursor_count; ++i) {
++ theme->cursors[i] =
++ wl_cursor_create_from_data(&cursor_metadata[i], theme);
++
++ if (theme->cursors[i] == NULL)
++ break;
++ }
++ theme->cursor_count = i;
++}
++
++static struct wl_cursor *
++wl_cursor_create_from_xcursor_images(struct xcursor_images *images,
++ struct wl_cursor_theme *theme)
++{
++ struct cursor *cursor;
++ struct cursor_image *image;
++ int i, size;
++
++ cursor = malloc(sizeof *cursor);
++ if (!cursor)
++ return NULL;
++
++ cursor->cursor.images =
++ malloc(images->nimage * sizeof cursor->cursor.images[0]);
++ if (!cursor->cursor.images) {
++ free(cursor);
++ return NULL;
++ }
++
++ cursor->cursor.name = strdup(images->name);
++ cursor->total_delay = 0;
++
++ for (i = 0; i < images->nimage; i++) {
++ image = malloc(sizeof *image);
++ if (image == NULL)
++ break;
++
++ image->theme = theme;
++ image->buffer = NULL;
++
++ image->image.width = images->images[i]->width;
++ image->image.height = images->images[i]->height;
++ image->image.hotspot_x = images->images[i]->xhot;
++ image->image.hotspot_y = images->images[i]->yhot;
++ image->image.delay = images->images[i]->delay;
++
++ size = image->image.width * image->image.height * 4;
++ image->offset = shm_pool_allocate(theme->pool, size);
++ if (image->offset < 0) {
++ free(image);
++ break;
++ }
++
++ /* copy pixels to shm pool */
++ memcpy(theme->pool->data + image->offset,
++ images->images[i]->pixels, size);
++ cursor->total_delay += image->image.delay;
++ cursor->cursor.images[i] = (struct wl_cursor_image *) image;
++ }
++ cursor->cursor.image_count = i;
++
++ if (cursor->cursor.image_count == 0) {
++ free(cursor->cursor.name);
++ free(cursor->cursor.images);
++ free(cursor);
++ return NULL;
++ }
++
++ return &cursor->cursor;
++}
++
++static void
++load_callback(struct xcursor_images *images, void *data)
++{
++ struct wl_cursor_theme *theme = data;
++ struct wl_cursor *cursor;
++
++ if (wl_cursor_theme_get_cursor(theme, images->name)) {
++ xcursor_images_destroy(images);
++ return;
++ }
++
++ cursor = wl_cursor_create_from_xcursor_images(images, theme);
++
++ if (cursor) {
++ theme->cursor_count++;
++ theme->cursors =
++ realloc(theme->cursors,
++ theme->cursor_count * sizeof theme->cursors[0]);
++
++ if (theme->cursors == NULL) {
++ theme->cursor_count--;
++ free(cursor);
++ } else {
++ theme->cursors[theme->cursor_count - 1] = cursor;
++ }
++ }
++
++ xcursor_images_destroy(images);
++}
++
++/** Load a cursor theme to memory shared with the compositor
++ *
++ * \param name The name of the cursor theme to load. If %NULL, the default
++ * theme will be loaded.
++ * \param size Desired size of the cursor images.
++ * \param shm The compositor's shm interface.
++ *
++ * \return An object representing the theme that should be destroyed with
++ * wl_cursor_theme_destroy() or %NULL on error. If no theme with the given
++ * name exists, a default theme will be loaded.
++ */
++WL_EXPORT struct wl_cursor_theme *
++wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
++{
++ struct wl_cursor_theme *theme;
++
++ theme = malloc(sizeof *theme);
++ if (!theme)
++ return NULL;
++
++ if (!name)
++ name = "default";
++
++ theme->size = size;
++ theme->cursor_count = 0;
++ theme->cursors = NULL;
++
++ theme->pool = shm_pool_create(shm, size * size * 4);
++ if (!theme->pool)
++ goto out_error_pool;
++
++ xcursor_load_theme(name, size, load_callback, theme);
++
++ if (theme->cursor_count == 0)
++ xcursor_load_theme(NULL, size, load_callback, theme);
++
++ if (theme->cursor_count == 0)
++ load_fallback_theme(theme);
++
++ return theme;
++
++out_error_pool:
++ free(theme);
++ return NULL;
++}
++
++/** Destroys a cursor theme object
++ *
++ * \param theme The cursor theme to be destroyed
++ */
++WL_EXPORT void
++wl_cursor_theme_destroy(struct wl_cursor_theme *theme)
++{
++ unsigned int i;
++
++ for (i = 0; i < theme->cursor_count; i++)
++ wl_cursor_destroy(theme->cursors[i]);
++
++ shm_pool_destroy(theme->pool);
++
++ free(theme->cursors);
++ free(theme);
++}
++
++/** Get the cursor for a given name from a cursor theme
++ *
++ * \param theme The cursor theme
++ * \param name Name of the desired cursor
++ * \return The theme's cursor of the given name or %NULL if there is no
++ * such cursor
++ */
++WL_EXPORT struct wl_cursor *
++wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
++ const char *name)
++{
++ unsigned int i;
++
++ for (i = 0; i < theme->cursor_count; i++) {
++ if (strcmp(name, theme->cursors[i]->name) == 0)
++ return theme->cursors[i];
++ }
++
++ return NULL;
++}
++
++/** Find the frame for a given elapsed time in a cursor animation
++ * as well as the time left until next cursor change.
++ *
++ * \param cursor The cursor
++ * \param time Elapsed time in ms since the beginning of the animation
++ * \param duration pointer to uint32_t to store time left for this image or
++ * zero if the cursor won't change.
++ *
++ * \return The index of the image that should be displayed for the
++ * given time in the cursor animation.
++ */
++WL_EXPORT int
++wl_cursor_frame_and_duration(struct wl_cursor *_cursor, uint32_t time,
++ uint32_t *duration)
++{
++ struct cursor *cursor = (struct cursor *) _cursor;
++ uint32_t t;
++ int i;
++
++ if (cursor->cursor.image_count == 1 || cursor->total_delay == 0) {
++ if (duration)
++ *duration = 0;
++ return 0;
++ }
++
++ i = 0;
++ t = time % cursor->total_delay;
++
++ /* If there is a 0 delay in the image set then this
++ * loop breaks on it and we display that cursor until
++ * time % cursor->total_delay wraps again.
++ * Since a 0 delay is silly, and we've never actually
++ * seen one in a cursor file, we haven't bothered to
++ * "fix" this.
++ */
++ while (t - cursor->cursor.images[i]->delay < t)
++ t -= cursor->cursor.images[i++]->delay;
++
++ if (!duration)
++ return i;
++
++ /* Make sure we don't accidentally tell the caller this is
++ * a static cursor image.
++ */
++ if (t >= cursor->cursor.images[i]->delay)
++ *duration = 1;
++ else
++ *duration = cursor->cursor.images[i]->delay - t;
++
++ return i;
++}
++
++/** Find the frame for a given elapsed time in a cursor animation
++ *
++ * \param cursor The cursor
++ * \param time Elapsed time in ms since the beginning of the animation
++ *
++ * \return The index of the image that should be displayed for the
++ * given time in the cursor animation.
++ */
++WL_EXPORT int
++wl_cursor_frame(struct wl_cursor *_cursor, uint32_t time)
++{
++ return wl_cursor_frame_and_duration(_cursor, time, NULL);
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_CURSOR_H
++#define WAYLAND_CURSOR_H
++
++#include <stdint.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct wl_cursor_theme;
++struct wl_buffer;
++struct wl_shm;
++
++/** A still image part of a cursor
++ *
++ * Use `wl_cursor_image_get_buffer()` to get the corresponding `struct
++ * wl_buffer` to attach to your `struct wl_surface`. */
++struct wl_cursor_image {
++ /** Actual width */
++ uint32_t width;
++
++ /** Actual height */
++ uint32_t height;
++
++ /** Hot spot x (must be inside image) */
++ uint32_t hotspot_x;
++
++ /** Hot spot y (must be inside image) */
++ uint32_t hotspot_y;
++
++ /** Animation delay to next frame (ms) */
++ uint32_t delay;
++};
++
++/** A cursor, as returned by `wl_cursor_theme_get_cursor()` */
++struct wl_cursor {
++ /** How many images there are in this cursor’s animation */
++ unsigned int image_count;
++
++ /** The array of still images composing this animation */
++ struct wl_cursor_image **images;
++
++ /** The name of this cursor */
++ char *name;
++};
++
++struct wl_cursor_theme *
++wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm);
++
++void
++wl_cursor_theme_destroy(struct wl_cursor_theme *theme);
++
++struct wl_cursor *
++wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
++ const char *name);
++
++struct wl_buffer *
++wl_cursor_image_get_buffer(struct wl_cursor_image *image);
++
++int
++wl_cursor_frame(struct wl_cursor *cursor, uint32_t time);
++
++int
++wl_cursor_frame_and_duration(struct wl_cursor *cursor, uint32_t time,
++ uint32_t *duration);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2002 Keith Packard
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++#include "xcursor.h"
++#include <stdbool.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <dirent.h>
++
++/*
++ * Cursor files start with a header. The header
++ * contains a magic number, a version number and a
++ * table of contents which has type and offset information
++ * for the remaining tables in the file.
++ *
++ * File minor versions increment for compatible changes
++ * File major versions increment for incompatible changes (never, we hope)
++ *
++ * Chunks of the same type are always upward compatible. Incompatible
++ * changes are made with new chunk types; the old data can remain under
++ * the old type. Upward compatible changes can add header data as the
++ * header lengths are specified in the file.
++ *
++ * File:
++ * FileHeader
++ * LISTofChunk
++ *
++ * FileHeader:
++ * CARD32 magic magic number
++ * CARD32 header bytes in file header
++ * CARD32 version file version
++ * CARD32 ntoc number of toc entries
++ * LISTofFileToc toc table of contents
++ *
++ * FileToc:
++ * CARD32 type entry type
++ * CARD32 subtype entry subtype (size for images)
++ * CARD32 position absolute file position
++ */
++
++#define XCURSOR_MAGIC 0x72756358 /* "Xcur" LSBFirst */
++
++/*
++ * This version number is stored in cursor files; changes to the
++ * file format require updating this version number
++ */
++#define XCURSOR_FILE_MAJOR 1
++#define XCURSOR_FILE_MINOR 0
++#define XCURSOR_FILE_VERSION ((XCURSOR_FILE_MAJOR << 16) | (XCURSOR_FILE_MINOR))
++#define XCURSOR_FILE_HEADER_LEN (4 * 4)
++#define XCURSOR_FILE_TOC_LEN (3 * 4)
++
++struct xcursor_file_toc {
++ uint32_t type; /* chunk type */
++ uint32_t subtype; /* subtype (size for images) */
++ uint32_t position; /* absolute position in file */
++};
++
++struct xcursor_file_header {
++ uint32_t magic; /* magic number */
++ uint32_t header; /* byte length of header */
++ uint32_t version; /* file version number */
++ uint32_t ntoc; /* number of toc entries */
++ struct xcursor_file_toc *tocs; /* table of contents */
++};
++
++/*
++ * The rest of the file is a list of chunks, each tagged by type
++ * and version.
++ *
++ * Chunk:
++ * ChunkHeader
++ * <extra type-specific header fields>
++ * <type-specific data>
++ *
++ * ChunkHeader:
++ * CARD32 header bytes in chunk header + type header
++ * CARD32 type chunk type
++ * CARD32 subtype chunk subtype
++ * CARD32 version chunk type version
++ */
++
++#define XCURSOR_CHUNK_HEADER_LEN (4 * 4)
++
++struct xcursor_chunk_header {
++ uint32_t header; /* bytes in chunk header */
++ uint32_t type; /* chunk type */
++ uint32_t subtype; /* chunk subtype (size for images) */
++ uint32_t version; /* version of this type */
++};
++
++/*
++ * Each cursor image occupies a separate image chunk.
++ * The length of the image header follows the chunk header
++ * so that future versions can extend the header without
++ * breaking older applications
++ *
++ * Image:
++ * ChunkHeader header chunk header
++ * CARD32 width actual width
++ * CARD32 height actual height
++ * CARD32 xhot hot spot x
++ * CARD32 yhot hot spot y
++ * CARD32 delay animation delay
++ * LISTofCARD32 pixels ARGB pixels
++ */
++
++#define XCURSOR_IMAGE_TYPE 0xfffd0002
++#define XCURSOR_IMAGE_VERSION 1
++#define XCURSOR_IMAGE_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (5*4))
++#define XCURSOR_IMAGE_MAX_SIZE 0x7fff /* 32767x32767 max cursor size */
++
++/*
++ * From libXcursor/src/file.c
++ */
++
++static struct xcursor_image *
++xcursor_image_create(int width, int height)
++{
++ struct xcursor_image *image;
++
++ if (width < 0 || height < 0)
++ return NULL;
++ if (width > XCURSOR_IMAGE_MAX_SIZE || height > XCURSOR_IMAGE_MAX_SIZE)
++ return NULL;
++
++ image = malloc(sizeof(struct xcursor_image) +
++ width * height * sizeof(uint32_t));
++ if (!image)
++ return NULL;
++ image->version = XCURSOR_IMAGE_VERSION;
++ image->pixels = (uint32_t *) (image + 1);
++ image->size = width > height ? width : height;
++ image->width = width;
++ image->height = height;
++ image->delay = 0;
++ return image;
++}
++
++static void
++xcursor_image_destroy(struct xcursor_image *image)
++{
++ free(image);
++}
++
++static struct xcursor_images *
++xcursor_images_create(int size)
++{
++ struct xcursor_images *images;
++
++ images = malloc(sizeof(struct xcursor_images) +
++ size * sizeof(struct xcursor_image *));
++ if (!images)
++ return NULL;
++ images->nimage = 0;
++ images->images = (struct xcursor_image **) (images + 1);
++ images->name = NULL;
++ return images;
++}
++
++void
++xcursor_images_destroy(struct xcursor_images *images)
++{
++ int n;
++
++ if (!images)
++ return;
++
++ for (n = 0; n < images->nimage; n++)
++ xcursor_image_destroy(images->images[n]);
++ free(images->name);
++ free(images);
++}
++
++static bool
++xcursor_read_uint(FILE *file, uint32_t *u)
++{
++ unsigned char bytes[4];
++
++ if (!file || !u)
++ return false;
++
++ if (fread(bytes, 1, 4, file) != 4)
++ return false;
++
++ *u = ((uint32_t)(bytes[0]) << 0) |
++ ((uint32_t)(bytes[1]) << 8) |
++ ((uint32_t)(bytes[2]) << 16) |
++ ((uint32_t)(bytes[3]) << 24);
++ return true;
++}
++
++static void
++xcursor_file_header_destroy(struct xcursor_file_header *file_header)
++{
++ free(file_header);
++}
++
++static struct xcursor_file_header *
++xcursor_file_header_create(uint32_t ntoc)
++{
++ struct xcursor_file_header *file_header;
++
++ if (ntoc > 0x10000)
++ return NULL;
++ file_header = malloc(sizeof(struct xcursor_file_header) +
++ ntoc * sizeof(struct xcursor_file_toc));
++ if (!file_header)
++ return NULL;
++ file_header->magic = XCURSOR_MAGIC;
++ file_header->header = XCURSOR_FILE_HEADER_LEN;
++ file_header->version = XCURSOR_FILE_VERSION;
++ file_header->ntoc = ntoc;
++ file_header->tocs = (struct xcursor_file_toc *) (file_header + 1);
++ return file_header;
++}
++
++static struct xcursor_file_header *
++xcursor_read_file_header(FILE *file)
++{
++ struct xcursor_file_header head, *file_header;
++ uint32_t skip;
++ unsigned int n;
++
++ if (!file)
++ return NULL;
++
++ if (!xcursor_read_uint(file, &head.magic))
++ return NULL;
++ if (head.magic != XCURSOR_MAGIC)
++ return NULL;
++ if (!xcursor_read_uint(file, &head.header))
++ return NULL;
++ if (!xcursor_read_uint(file, &head.version))
++ return NULL;
++ if (!xcursor_read_uint(file, &head.ntoc))
++ return NULL;
++ skip = head.header - XCURSOR_FILE_HEADER_LEN;
++ if (skip)
++ if (fseek(file, skip, SEEK_CUR) == EOF)
++ return NULL;
++ file_header = xcursor_file_header_create(head.ntoc);
++ if (!file_header)
++ return NULL;
++ file_header->magic = head.magic;
++ file_header->header = head.header;
++ file_header->version = head.version;
++ file_header->ntoc = head.ntoc;
++ for (n = 0; n < file_header->ntoc; n++) {
++ if (!xcursor_read_uint(file, &file_header->tocs[n].type))
++ break;
++ if (!xcursor_read_uint(file, &file_header->tocs[n].subtype))
++ break;
++ if (!xcursor_read_uint(file, &file_header->tocs[n].position))
++ break;
++ }
++ if (n != file_header->ntoc) {
++ xcursor_file_header_destroy(file_header);
++ return NULL;
++ }
++ return file_header;
++}
++
++static bool
++xcursor_seek_to_toc(FILE *file,
++ struct xcursor_file_header *file_header,
++ int toc)
++{
++ if (!file || !file_header ||
++ fseek(file, file_header->tocs[toc].position, SEEK_SET) == EOF)
++ return false;
++ return true;
++}
++
++static bool
++xcursor_file_read_chunk_header(FILE *file,
++ struct xcursor_file_header *file_header,
++ int toc,
++ struct xcursor_chunk_header *chunk_header)
++{
++ if (!file || !file_header || !chunk_header)
++ return false;
++ if (!xcursor_seek_to_toc(file, file_header, toc))
++ return false;
++ if (!xcursor_read_uint(file, &chunk_header->header))
++ return false;
++ if (!xcursor_read_uint(file, &chunk_header->type))
++ return false;
++ if (!xcursor_read_uint(file, &chunk_header->subtype))
++ return false;
++ if (!xcursor_read_uint(file, &chunk_header->version))
++ return false;
++ /* sanity check */
++ if (chunk_header->type != file_header->tocs[toc].type ||
++ chunk_header->subtype != file_header->tocs[toc].subtype)
++ return false;
++ return true;
++}
++
++static uint32_t
++dist(uint32_t a, uint32_t b)
++{
++ return a > b ? a - b : b - a;
++}
++
++static uint32_t
++xcursor_file_best_size(struct xcursor_file_header *file_header,
++ uint32_t size, int *nsizesp)
++{
++ unsigned int n;
++ int nsizes = 0;
++ uint32_t best_size = 0;
++ uint32_t this_size;
++
++ if (!file_header || !nsizesp)
++ return 0;
++
++ for (n = 0; n < file_header->ntoc; n++) {
++ if (file_header->tocs[n].type != XCURSOR_IMAGE_TYPE)
++ continue;
++ this_size = file_header->tocs[n].subtype;
++ if (!best_size || dist(this_size, size) < dist(best_size, size)) {
++ best_size = this_size;
++ nsizes = 1;
++ } else if (this_size == best_size) {
++ nsizes++;
++ }
++ }
++ *nsizesp = nsizes;
++ return best_size;
++}
++
++static int
++xcursor_find_image_toc(struct xcursor_file_header *file_header,
++ uint32_t size, int count)
++{
++ unsigned int toc;
++ uint32_t this_size;
++
++ if (!file_header)
++ return 0;
++
++ for (toc = 0; toc < file_header->ntoc; toc++) {
++ if (file_header->tocs[toc].type != XCURSOR_IMAGE_TYPE)
++ continue;
++ this_size = file_header->tocs[toc].subtype;
++ if (this_size != size)
++ continue;
++ if (!count)
++ break;
++ count--;
++ }
++ if (toc == file_header->ntoc)
++ return -1;
++ return toc;
++}
++
++static struct xcursor_image *
++xcursor_read_image(FILE *file,
++ struct xcursor_file_header *file_header,
++ int toc)
++{
++ struct xcursor_chunk_header chunk_header;
++ struct xcursor_image head;
++ struct xcursor_image *image;
++ int n;
++ uint32_t *p;
++
++ if (!file || !file_header)
++ return NULL;
++
++ if (!xcursor_file_read_chunk_header(file, file_header, toc, &chunk_header))
++ return NULL;
++ if (!xcursor_read_uint(file, &head.width))
++ return NULL;
++ if (!xcursor_read_uint(file, &head.height))
++ return NULL;
++ if (!xcursor_read_uint(file, &head.xhot))
++ return NULL;
++ if (!xcursor_read_uint(file, &head.yhot))
++ return NULL;
++ if (!xcursor_read_uint(file, &head.delay))
++ return NULL;
++ /* sanity check data */
++ if (head.width > XCURSOR_IMAGE_MAX_SIZE ||
++ head.height > XCURSOR_IMAGE_MAX_SIZE)
++ return NULL;
++ if (head.width == 0 || head.height == 0)
++ return NULL;
++ if (head.xhot > head.width || head.yhot > head.height)
++ return NULL;
++
++ /* Create the image and initialize it */
++ image = xcursor_image_create(head.width, head.height);
++ if (image == NULL)
++ return NULL;
++ if (chunk_header.version < image->version)
++ image->version = chunk_header.version;
++ image->size = chunk_header.subtype;
++ image->xhot = head.xhot;
++ image->yhot = head.yhot;
++ image->delay = head.delay;
++ n = image->width * image->height;
++ p = image->pixels;
++ while (n--) {
++ if (!xcursor_read_uint(file, p)) {
++ xcursor_image_destroy(image);
++ return NULL;
++ }
++ p++;
++ }
++ return image;
++}
++
++static struct xcursor_images *
++xcursor_xc_file_load_images(FILE *file, int size)
++{
++ struct xcursor_file_header *file_header;
++ uint32_t best_size;
++ int nsize;
++ struct xcursor_images *images;
++ int n;
++ int toc;
++
++ if (!file || size < 0)
++ return NULL;
++ file_header = xcursor_read_file_header(file);
++ if (!file_header)
++ return NULL;
++ best_size = xcursor_file_best_size(file_header, (uint32_t) size, &nsize);
++ if (!best_size) {
++ xcursor_file_header_destroy(file_header);
++ return NULL;
++ }
++ images = xcursor_images_create(nsize);
++ if (!images) {
++ xcursor_file_header_destroy(file_header);
++ return NULL;
++ }
++ for (n = 0; n < nsize; n++) {
++ toc = xcursor_find_image_toc(file_header, best_size, n);
++ if (toc < 0)
++ break;
++ images->images[images->nimage] = xcursor_read_image(file, file_header,
++ toc);
++ if (!images->images[images->nimage])
++ break;
++ images->nimage++;
++ }
++ xcursor_file_header_destroy(file_header);
++ if (images->nimage != nsize) {
++ xcursor_images_destroy(images);
++ images = NULL;
++ }
++ return images;
++}
++
++/*
++ * From libXcursor/src/library.c
++ */
++
++#ifndef ICONDIR
++#define ICONDIR "/usr/X11R6/lib/X11/icons"
++#endif
++
++#ifndef XCURSORPATH
++#define XCURSORPATH "~/.icons:/usr/share/icons:/usr/share/pixmaps:~/.cursors:/usr/share/cursors/xorg-x11:"ICONDIR
++#endif
++
++#define XDG_DATA_HOME_FALLBACK "~/.local/share"
++#define CURSORDIR "/icons"
++
++/** Get search path for cursor themes
++ *
++ * This function builds the list of directories to look for cursor
++ * themes in. The format is PATH-like: directories are separated by
++ * colons.
++ *
++ * The memory block returned by this function is allocated on the heap
++ * and must be freed by the caller.
++ */
++static char *
++xcursor_library_path(void)
++{
++ const char *env_var, *suffix;
++ char *path;
++ size_t path_size;
++
++ env_var = getenv("XCURSOR_PATH");
++ if (env_var)
++ return strdup(env_var);
++
++ env_var = getenv("XDG_DATA_HOME");
++ if (!env_var || env_var[0] != '/')
++ env_var = XDG_DATA_HOME_FALLBACK;
++
++ suffix = CURSORDIR ":" XCURSORPATH;
++ path_size = strlen(env_var) + strlen(suffix) + 1;
++ path = malloc(path_size);
++ if (!path)
++ return NULL;
++ snprintf(path, path_size, "%s%s", env_var, suffix);
++ return path;
++}
++
++static char *
++xcursor_build_theme_dir(const char *dir, const char *theme)
++{
++ const char *colon;
++ const char *tcolon;
++ char *full;
++ const char *home, *homesep;
++ int dirlen;
++ int homelen;
++ int themelen;
++ size_t full_size;
++
++ if (!dir || !theme)
++ return NULL;
++
++ colon = strchr(dir, ':');
++ if (!colon)
++ colon = dir + strlen(dir);
++
++ dirlen = colon - dir;
++
++ tcolon = strchr(theme, ':');
++ if (!tcolon)
++ tcolon = theme + strlen(theme);
++
++ themelen = tcolon - theme;
++
++ home = "";
++ homelen = 0;
++ homesep = "";
++ if (*dir == '~') {
++ home = getenv("HOME");
++ if (!home)
++ return NULL;
++ homelen = strlen(home);
++ homesep = "/";
++ dir++;
++ dirlen--;
++ }
++
++ /*
++ * add space for any needed directory separators, one per component,
++ * and one for the trailing null
++ */
++ full_size = 1 + homelen + 1 + dirlen + 1 + themelen + 1;
++ full = malloc(full_size);
++ if (!full)
++ return NULL;
++ snprintf(full, full_size, "%s%s%.*s/%.*s", home, homesep,
++ dirlen, dir, themelen, theme);
++ return full;
++}
++
++static char *
++xcursor_build_fullname(const char *dir, const char *subdir, const char *file)
++{
++ char *full;
++ size_t full_size;
++
++ if (!dir || !subdir || !file)
++ return NULL;
++
++ full_size = strlen(dir) + 1 + strlen(subdir) + 1 + strlen(file) + 1;
++ full = malloc(full_size);
++ if (!full)
++ return NULL;
++ snprintf(full, full_size, "%s/%s/%s", dir, subdir, file);
++ return full;
++}
++
++static const char *
++xcursor_next_path(const char *path)
++{
++ char *colon = strchr(path, ':');
++
++ if (!colon)
++ return NULL;
++ return colon + 1;
++}
++
++static bool
++xcursor_white(char c)
++{
++ return c == ' ' || c == '\t' || c == '\n';
++}
++
++static bool
++xcursor_sep(char c)
++{
++ return c == ';' || c == ',';
++}
++
++static char *
++xcursor_theme_inherits(const char *full)
++{
++ char *line = NULL;
++ size_t line_size = 0;
++ char *result = NULL;
++ FILE *f;
++
++ if (!full)
++ return NULL;
++
++ f = fopen(full, "r");
++ if (!f)
++ return NULL;
++
++ while (getline(&line, &line_size, f) >= 0) {
++ const char *l;
++ char *r;
++
++ if (strncmp(line, "Inherits", 8))
++ continue;
++
++ l = line + 8;
++ while (*l == ' ')
++ l++;
++ if (*l != '=')
++ continue;
++ l++;
++ while (*l == ' ')
++ l++;
++ result = malloc(strlen(l) + 1);
++ if (!result)
++ break;
++
++ r = result;
++ while (*l) {
++ while (xcursor_sep(*l) || xcursor_white(*l))
++ l++;
++ if (!*l)
++ break;
++ if (r != result)
++ *r++ = ':';
++ while (*l && !xcursor_white(*l) && !xcursor_sep(*l))
++ *r++ = *l++;
++ }
++ *r++ = '\0';
++
++ break;
++ }
++
++ fclose(f);
++ free(line);
++
++ return result;
++}
++
++static void
++load_all_cursors_from_dir(const char *path, int size,
++ void (*load_callback)(struct xcursor_images *, void *),
++ void *user_data)
++{
++ FILE *f;
++ DIR *dir = opendir(path);
++ struct dirent *ent;
++ char *full;
++ struct xcursor_images *images;
++
++ if (!dir)
++ return;
++
++ for (ent = readdir(dir); ent; ent = readdir(dir)) {
++#ifdef _DIRENT_HAVE_D_TYPE
++ if (ent->d_type != DT_UNKNOWN &&
++ ent->d_type != DT_REG &&
++ ent->d_type != DT_LNK)
++ continue;
++#endif
++
++ full = xcursor_build_fullname(path, "", ent->d_name);
++ if (!full)
++ continue;
++
++ f = fopen(full, "r");
++ if (!f) {
++ free(full);
++ continue;
++ }
++
++ images = xcursor_xc_file_load_images(f, size);
++
++ if (images) {
++ images->name = strdup(ent->d_name);
++ load_callback(images, user_data);
++ }
++
++ fclose(f);
++ free(full);
++ }
++
++ closedir(dir);
++}
++
++/** Load all the cursor of a theme
++ *
++ * This function loads all the cursor images of a given theme and its
++ * inherited themes. Each cursor is loaded into an struct xcursor_images object
++ * which is passed to the caller's load callback. If a cursor appears
++ * more than once across all the inherited themes, the load callback
++ * will be called multiple times, with possibly different struct xcursor_images
++ * object which have the same name. The user is expected to destroy the
++ * struct xcursor_images objects passed to the callback with
++ * xcursor_images_destroy().
++ *
++ * \param theme The name of theme that should be loaded
++ * \param size The desired size of the cursor images
++ * \param load_callback A callback function that will be called
++ * for each cursor loaded. The first parameter is the struct xcursor_images
++ * object representing the loaded cursor and the second is a pointer
++ * to data provided by the user.
++ * \param user_data The data that should be passed to the load callback
++ */
++void
++xcursor_load_theme(const char *theme, int size,
++ void (*load_callback)(struct xcursor_images *, void *),
++ void *user_data)
++{
++ char *full, *dir;
++ char *inherits = NULL;
++ const char *path, *i;
++ char *xcursor_path;
++
++ if (!theme)
++ theme = "default";
++
++ xcursor_path = xcursor_library_path();
++ for (path = xcursor_path;
++ path;
++ path = xcursor_next_path(path)) {
++ dir = xcursor_build_theme_dir(path, theme);
++ if (!dir)
++ continue;
++
++ full = xcursor_build_fullname(dir, "cursors", "");
++ load_all_cursors_from_dir(full, size, load_callback,
++ user_data);
++ free(full);
++
++ if (!inherits) {
++ full = xcursor_build_fullname(dir, "", "index.theme");
++ inherits = xcursor_theme_inherits(full);
++ free(full);
++ }
++
++ free(dir);
++ }
++
++ for (i = inherits; i; i = xcursor_next_path(i))
++ xcursor_load_theme(i, size, load_callback, user_data);
++
++ free(inherits);
++ free(xcursor_path);
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2002 Keith Packard
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef XCURSOR_H
++#define XCURSOR_H
++
++#include <stdint.h>
++
++struct xcursor_image {
++ uint32_t version; /* version of the image data */
++ uint32_t size; /* nominal size for matching */
++ uint32_t width; /* actual width */
++ uint32_t height; /* actual height */
++ uint32_t xhot; /* hot spot x (must be inside image) */
++ uint32_t yhot; /* hot spot y (must be inside image) */
++ uint32_t delay; /* animation delay to next frame (ms) */
++ uint32_t *pixels; /* pointer to pixels */
++};
++
++/*
++ * Other data structures exposed by the library API
++ */
++struct xcursor_images {
++ int nimage; /* number of images */
++ struct xcursor_image **images; /* array of XcursorImage pointers */
++ char *name; /* name used to load images */
++};
++
++void
++xcursor_images_destroy(struct xcursor_images *images);
++
++void
++xcursor_load_theme(const char *theme, int size,
++ void (*load_callback)(struct xcursor_images *, void *),
++ void *user_data);
++#endif
--- /dev/null
--- /dev/null
++doxygen_sqlite3.db
++html/
++wayland.doxygen
--- /dev/null
--- /dev/null
++digraph arch_wayland {
++ edge[
++ fontname="DejaVu Sans",
++ dir="both",
++ arrowtail="dot",
++ arrowsize=.5,
++ fontname="DejaVu Sans",
++ fontsize="18",
++ ]
++
++ node[
++ color=none,
++ margin=0,
++ fontname="DejaVu Sans",
++ fontsize="18",
++ ]
++
++ c1 [label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD>Wayland Client</TD></TR></TABLE>>, URL="#c1"]
++ c2 [label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD>Wayland Client</TD></TR></TABLE>>, URL="#c2"]
++
++ comp [tooltip="Wayland Compositor", label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD><BR/>Wayland<BR/>Compositor<BR/><BR/></TD></TR></TABLE>>, URL="#comp"]
++
++ impl [tooltip="KMS evdev Kernel", label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD>KMS</TD><TD>evdev</TD></TR><TR><TD COLSPAN="2">Kernel</TD></TR></TABLE>>, URL="#impl"]
++
++ c1 -> comp [taillabel="③", labeldistance=2.5, URL="#step_3"];
++ c2 -> comp;
++
++ comp -> c1 [label="②", URL="#step_2"];
++ comp -> c2;
++
++ comp -> impl [xlabel = "④", URL="#step_4"];
++ comp -> impl [style = invis, label=" "];
++ impl -> comp [xlabel = "①", URL="#step_1"];
++
++ c1 -> c2 [style=invis];
++}
--- /dev/null
--- /dev/null
++digraph arch_x {
++ edge[
++ fontname="DejaVu Sans",
++ dir="both",
++ arrowtail="dot",
++ arrowsize=.5,
++ fontname="DejaVu Sans",
++ fontsize="18",
++ ]
++
++ node[
++ shape="none",
++ color=none,
++ margin=0,
++ fontname="DejaVu Sans",
++ fontsize="18",
++ ]
++
++ {
++ rank=same;
++ c1 [label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD>X Client</TD></TR></TABLE>>, URL="#c1"]
++ c3 [label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD>X Client</TD></TR></TABLE>>, URL="#c3"]
++ }
++ c2 [label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD>X Client</TD></TR></TABLE>>, URL="#c2"]
++
++ {
++ rank=same;
++ xserver [tooltip="X Server", label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD><BR/>X Server<BR/><BR/></TD></TR></TABLE>>, URL="#xserver"]
++ comp [tooltip="Compositor", label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD><BR/>Compositor<BR/><BR/></TD></TR></TABLE>>, URL="#comp"]
++ }
++
++ impl [tooltip="KMS evdev Kernel", label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD>KMS</TD><TD>evdev</TD></TR><TR><TD COLSPAN="2">Kernel</TD></TR></TABLE>>, URL="#impl"]
++
++ c1 -> xserver [taillabel="③", labeldistance=2, URL="#step_3"];
++ c2 -> xserver;
++ c3 -> xserver;
++
++ xserver -> c1 [taillabel="②", labeldistance=2, URL="#step_2"];
++ xserver -> c2;
++ xserver -> c3;
++
++ xserver -> impl [taillabel="⑥", labeldistance=1.75, URL="#step_6"];
++ xserver -> impl [style=invis, label=" "];
++ impl -> xserver [taillabel="①", labeldistance=1.75, URL="#step_1"];
++
++ xserver -> comp [style=invis];
++ xserver -> comp [taillabel="④", labeldistance=1.75, labelangle=-45, URL="#step_4"];
++ comp -> xserver [taillabel="⑤", URL="#step_5"];
++ comp -> xserver [style=invis]
++
++ c1 -> c2 [style=invis];
++ c3 -> c2 [style=invis];
++ }
--- /dev/null
--- /dev/null
++#!/usr/bin/env python3
++
++import argparse
++import datetime
++import errno
++import os
++import subprocess
++import sys
++
++# Custom configuration for each documentation format
++doxygen_templates = {
++ 'xml': [
++ 'GENERATE_XML=YES\n',
++ 'XML_OUTPUT={format}/{section}\n',
++ 'INPUT= {files}\n',
++ ],
++ 'html': [
++ 'GENERATE_HTML=YES\n',
++ 'HTML_OUTPUT={format}/{section}\n',
++ 'PROJECT_NAME=\"Wayland {section} API\"\n',
++ 'INPUT= {files}\n',
++ ],
++ 'man': [
++ 'GENERATE_MAN=YES\n',
++ 'MAN_OUTPUT={format}\n',
++ 'MAN_SUBDIR=.\n',
++ 'JAVADOC_AUTOBRIEF=NO\n',
++ 'INPUT= {files}\n',
++ ],
++}
++
++def load_doxygen_file(doxyfile):
++ with open(doxyfile, 'r') as f:
++ res = f.readlines()
++ return res
++
++def get_template(outformat):
++ for (k,v) in doxygen_templates.items():
++ if outformat.startswith(k):
++ return v
++
++def gen_doxygen_file(data, outformat, section, files):
++ for l in get_template(outformat):
++ data.append(l.format(format=outformat, section=section, files=' '.join(files)))
++ return data
++
++parser = argparse.ArgumentParser(description='Generate docs with Doxygen')
++parser.add_argument('doxygen_file',
++ help='The doxygen file to use')
++parser.add_argument('files',
++ help='The list of files to parse',
++ metavar='FILES',
++ nargs='+')
++parser.add_argument('--builddir',
++ help='The build directory',
++ metavar='DIR',
++ default='.')
++parser.add_argument('--section',
++ help='The section to build',
++ metavar='NAME',
++ default='Client')
++parser.add_argument('--output-format',
++ help='The output format: xml, html, man',
++ metavar='FORMAT',
++ default='xml')
++parser.add_argument('--stamp',
++ help='Stamp file to output',
++ metavar='STAMP_FILE',
++ nargs='?',
++ type=argparse.FileType('w'))
++
++args = parser.parse_args()
++
++# Merge the doxyfile with our custom templates
++conf = load_doxygen_file(args.doxygen_file)
++conf = gen_doxygen_file(conf, args.output_format, args.section, args.files)
++
++# Doxygen is not clever enough to create the directories it
++# needs beforehand
++try:
++ os.makedirs(os.path.join(args.builddir, args.output_format))
++except OSError as e:
++ if e.errno != errno.EEXIST:
++ raise e
++
++# Run Doxygen with the generated doxyfile
++cmd = subprocess.Popen(['doxygen', '-'], stdin=subprocess.PIPE)
++cmd.stdin.write(''.join(conf).encode('utf-8'))
++cmd.stdin.close()
++if cmd.wait() != 0:
++ sys.exit(1)
++
++# This is a bit of a hack; Doxygen will generate way more files than we
++# want to install, but there's no way to know how many at configuration
++# time. Since we want to install only the wl_* man pages anyway, we can
++# delete the other files and let Meson install the whole man3 subdirectory
++if args.output_format.startswith('man'):
++ manpath = os.path.join(args.builddir, args.output_format)
++ for filename in os.listdir(manpath):
++ full_path = os.path.join(manpath, filename)
++ if not filename.startswith('wl_'):
++ os.remove(full_path)
++
++if args.stamp:
++ args.stamp.write(str(datetime.datetime.now()))
--- /dev/null
--- /dev/null
++/**
++ * @mainpage
++ * Wayland protocol API documentation.
++ *
++ * This documentation is available for the Server- and the Client-side APIs.
++ *
++ * - <a href="../Server/index.html">Server-side API</a>
++ * - <a href="../Client/index.html">Client-side API</a>
++ * - <a href="../Cursor/index.html">Cursor helper library API</a>
++ *
++ * Further documentation about the architecture and principles of Wayland is
++ * available in the
++ * <a href="https://wayland.freedesktop.org/docs/html">Wayland Book</a>
++ *
++ * @section ifaces Interfaces
++ * For the list of available interfaces, please see the
++ * <a href="modules.html">modules</a> list.
++ *
++ * @section protocols Protocols
++ * For the list of protocols, please see the
++ * <a href="pages.html">Related Pages</a>.
++ *
++ */
--- /dev/null
--- /dev/null
++# Here be dragons
++
++dot_gv = {
++ 'wayland-architecture': files('dot/wayland-architecture.gv'),
++ 'x-architecture': files('dot/x-architecture.gv'),
++}
++
++# This is a workaround for Meson's custom_target() directive, which
++# currently does not support outputs pointing to a sub-directory
++# XXX: try turning these into maps, so they can be indexed with picture name
++dot_png = []
++dot_map = []
++
++doxygen_conf = configuration_data()
++doxygen_conf.set('VERSION', meson.project_version())
++doxygen_conf.set('top_builddir', meson.project_build_root())
++wayland_doxygen = configure_file(
++ input: 'wayland.doxygen.in',
++ output: 'wayland.doxygen',
++ configuration: doxygen_conf,
++)
++
++shared_files = files([
++ '../../src/wayland-util.h',
++])
++
++client_files = files([
++ '../../src/wayland-client.c',
++ '../../src/wayland-client.h',
++ '../../src/wayland-client-core.h',
++])
++
++server_files = files([
++ '../../src/event-loop.c',
++ '../../src/wayland-server.c',
++ '../../src/wayland-server.h',
++ '../../src/wayland-server-core.h',
++ '../../src/wayland-shm.c',
++])
++
++cursor_files = files([
++ '../../cursor/wayland-cursor.c',
++ '../../cursor/wayland-cursor.h',
++])
++
++extra_client_files = [
++ 'mainpage.dox',
++ wayland_client_protocol_h,
++]
++
++extra_server_files = [
++ 'mainpage.dox',
++ wayland_server_protocol_h,
++]
++
++extra_cursor_files = [
++ 'mainpage.dox',
++]
++
++gen_doxygen = find_program('gen-doxygen.py')
++
++subdir('xml')
++
++formats = {
++ 'html': {
++ 'Client': shared_files + client_files + extra_client_files,
++ 'Server': shared_files + server_files + extra_server_files,
++ 'Cursor': shared_files + cursor_files + extra_cursor_files,
++ },
++}
++
++foreach f_name, sections: formats
++ foreach s_name, s_files: sections
++ t_name = '@0@-@1@-doc'.format(f_name, s_name)
++
++ # We do not really need an output file, but Meson
++ # will complain if one is not set, so we use a
++ # dummy 'stamp' file
++ stamp = join_paths(meson.current_build_dir(), '@0@.stamp'.format(t_name))
++ custom_target(
++ t_name,
++ command: [
++ gen_doxygen,
++ # XXX pass doxygen path as argument
++ '--builddir=@OUTDIR@',
++ '--section=@0@'.format(s_name),
++ '--output-format=@0@'.format(f_name),
++ '--stamp=@0@'.format(stamp),
++ wayland_doxygen,
++ '@INPUT@',
++ ],
++ input: s_files,
++ output: '@0@.stamp'.format(t_name),
++ depends: [dot_png, dot_map],
++ build_by_default: true,
++ )
++ endforeach
++endforeach
++
++man_files = shared_files + server_files + client_files + cursor_files
++stamp = join_paths(meson.current_build_dir(), 'man3.stamp')
++custom_target(
++ 'man-pages-3',
++ command: [
++ gen_doxygen,
++ '--builddir=@OUTDIR@',
++ '--output-format=man3',
++ '--stamp=@0@'.format(stamp),
++ wayland_doxygen,
++ '@INPUT@',
++ ],
++ input: man_files,
++ output: 'man3',
++ build_by_default: true,
++ install: true,
++ install_dir: join_paths(get_option('prefix'), get_option('mandir')),
++)
--- /dev/null
--- /dev/null
++# Wayland-specific overrides
++PROJECT_NAME = "Wayland"
++PROJECT_NUMBER = @VERSION@
++OUTPUT_DIRECTORY = @top_builddir@/doc/doxygen
++JAVADOC_AUTOBRIEF = YES
++TAB_SIZE = 8
++QUIET = YES
++HTML_TIMESTAMP = YES
++GENERATE_LATEX = NO
++MAN_LINKS = NO
++PREDEFINED = WL_EXPORT= \
++ WL_PRINTF(x,y)=
++MACRO_EXPANSION = YES
++EXPAND_ONLY_PREDEF = YES
++DOT_MULTI_TARGETS = YES
++ALIASES += comment{1}="/* \1 *<!-- -->/"
++OPTIMIZE_OUTPUT_FOR_C = YES
++EXTRACT_ALL = YES
++EXTRACT_STATIC = YES
++# These must be set in the Makefile
++GENERATE_HTML = NO
++GENERATE_XML = NO
++GENERATE_MAN = NO
--- /dev/null
--- /dev/null
++tgt = custom_target(
++ 'xml-Client-doc',
++ command: [
++ gen_doxygen,
++ # XXX pass doxygen path as argument
++ '--builddir=@OUTDIR@',
++ '--section=Client',
++ '--output-format=xml',
++ wayland_doxygen,
++ '@INPUT@',
++ ],
++ input: [ shared_files, client_files ],
++ output: [ 'combine.xslt', 'index.xml' ],
++ depends: [dot_png, dot_map]
++)
++
++doxygen_Client_combine_xslt = tgt[0]
++doxygen_Client_index_xml = tgt[1]
--- /dev/null
--- /dev/null
++tgt = custom_target(
++ 'xml-Server-doc',
++ command: [
++ gen_doxygen,
++ # XXX pass doxygen path as argument
++ '--builddir=@OUTDIR@',
++ '--section=Server',
++ '--output-format=xml',
++ wayland_doxygen,
++ '@INPUT@',
++ ],
++ input: [ shared_files, server_files ],
++ output: [ 'combine.xslt', 'index.xml' ],
++ depends: [dot_png, dot_map]
++)
++
++doxygen_Server_combine_xslt = tgt[0]
++doxygen_Server_index_xml = tgt[1]
--- /dev/null
--- /dev/null
++# dot_png: list of PNG targets
++# dot_map: list of MAP targets
++foreach name, infile: dot_gv
++ dot_png += custom_target(
++ name + '.png',
++ command: [ dot, '-Tpng', '-o@OUTPUT@', '@INPUT@' ],
++ input: infile,
++ output: name + '.png',
++ install: true,
++ install_dir: join_paths(publican_install_prefix, publican_html_dir, 'images')
++ )
++
++ dot_map += custom_target(
++ name + '.map',
++ command: [ dot, '-Tcmapx_np', '-o@OUTPUT@', '@INPUT@' ],
++ input: infile,
++ output: name + '.map',
++ )
++endforeach
++
++subdir('Client')
++subdir('Server')
--- /dev/null
--- /dev/null
++if not get_option('libraries')
++ error('-Ddocumentation=true requires -Dlibraries=true')
++endif
++
++dot = find_program('dot')
++doxygen = find_program('doxygen')
++xsltproc = find_program('xsltproc')
++xmlto = find_program('xmlto')
++
++cmd = run_command(doxygen, '--version', check: true)
++message('doxygen: ' + cmd.stdout().strip())
++vers = cmd.stdout().strip()
++if vers.version_compare('< 1.6.0')
++ error('Doxygen 1.6 or later is required for building documentation, found @0@.'.format(vers))
++endif
++
++cmd = run_command(dot, '-V', check: true)
++message('dot: ' + cmd.stderr().strip())
++vers = cmd.stderr().split('version')[1].strip().split(' ')[0]
++if vers.version_compare('< 2.26.0')
++ error('Dot (Graphviz) 2.26 or later is required for building documentation, found @0@.'.format(vers))
++endif
++
++manpage_xsl = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl'
++cmd = run_command(xsltproc, '--nonet', manpage_xsl, check: false)
++if cmd.returncode() != 0
++ error('The style sheet for man pages providing "@0@" was not found.'.format(manpage_xsl))
++endif
++
++publican_install_prefix = join_paths(
++ get_option('prefix'),
++ get_option('datadir'),
++ 'doc',
++ meson.project_name(),
++ 'Wayland', 'en-US'
++)
++
++publican_html_dir = 'html'
++
++subdir('doxygen')
++subdir('publican')
--- /dev/null
--- /dev/null
++Wayland
++en-US/
++publican-copy.cfg
--- /dev/null
--- /dev/null
++<?xml version="1.0" ?>
++<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
++<xsl:output method="xml" encoding="UTF-8" indent="yes" />
++<xsl:param name="which" />
++
++<xsl:template match="/">
++ <xsl:apply-templates select="/doxygen/compounddef[@kind!='file' and @kind!='dir']" />
++
++ <section id="{$which}-Functions">
++ <title>Functions</title>
++ <para />
++ <variablelist>
++ <xsl:apply-templates select="/doxygen/compounddef[@kind='file']/sectiondef/memberdef" />
++ </variablelist>
++ </section>
++
++</xsl:template>
++
++<xsl:template match="parameteritem">
++ <varlistentry>
++ <term>
++ <xsl:apply-templates select="parameternamelist/parametername"/>
++ </term>
++ <listitem>
++ <simpara><xsl:apply-templates select="parameterdescription"/></simpara>
++ </listitem>
++ </varlistentry>
++</xsl:template>
++
++<xsl:template match="parameterlist">
++ <xsl:if test="parameteritem">
++ <variablelist>
++ <xsl:apply-templates select="parameteritem" />
++ </variablelist>
++ </xsl:if>
++</xsl:template>
++
++<xsl:template match="ref">
++ <link linkend="{$which}-{@refid}"><xsl:value-of select="." /></link>
++</xsl:template>
++
++<xsl:template match="simplesect[@kind='return']">
++ <variablelist>
++ <varlistentry>
++ <term>Returns:</term>
++ <listitem>
++ <simpara><xsl:apply-templates /></simpara>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++</xsl:template>
++
++<xsl:template match="simplesect[@kind='see']">
++ See also: <xsl:apply-templates />
++</xsl:template>
++
++<xsl:template match="simplesect[@kind='since']">
++ Since: <xsl:apply-templates />
++</xsl:template>
++
++<xsl:template match="simplesect[@kind='note']">
++ <emphasis>Note: <xsl:apply-templates /></emphasis>
++</xsl:template>
++
++<xsl:template match="sp">
++ <xsl:text> </xsl:text>
++</xsl:template>
++
++<xsl:template match="programlisting">
++ <programlisting><xsl:apply-templates /></programlisting>
++</xsl:template>
++
++<xsl:template match="itemizedlist">
++ <itemizedlist><xsl:apply-templates select="listitem" /></itemizedlist>
++</xsl:template>
++
++<xsl:template match="listitem">
++ <listitem><simpara><xsl:apply-templates /></simpara></listitem>
++</xsl:template>
++
++<!-- stops cross-references in the section titles -->
++<xsl:template match="briefdescription">
++ <xsl:value-of select="." />
++</xsl:template>
++
++<!-- this opens a para for each detaileddescription/para. I could not find a
++ way to extract the right text for the description from the
++ source otherwise. Downside: we can't use para for return value, "see
++ also", etc. because they're already inside a para. So they're lists.
++
++ It also means we don't control the order of when something is added to
++ the output, it matches the input file
++ -->
++<xsl:template match="detaileddescription/para">
++ <para><xsl:apply-templates /></para>
++</xsl:template>
++
++<xsl:template match="detaileddescription">
++ <xsl:apply-templates select="para" />
++</xsl:template>
++
++<!-- methods -->
++<xsl:template match="memberdef" >
++ <xsl:if test="@kind = 'function' and @static = 'no' and @prot = 'public' or
++ @kind !='function' and normalize-space(briefdescription) != ''">
++ <varlistentry id="{$which}-{@id}">
++ <term>
++ <xsl:value-of select="name"/>
++ <xsl:if test="normalize-space(briefdescription) != ''">
++ - <xsl:apply-templates select="briefdescription" />
++ </xsl:if>
++ </term>
++ <listitem>
++ <synopsis>
++ <xsl:apply-templates select="definition"/><xsl:apply-templates select="argsstring"/>
++ </synopsis>
++ <xsl:apply-templates select="detaileddescription" />
++ </listitem>
++ </varlistentry>
++ </xsl:if>
++</xsl:template>
++
++<!-- classes -->
++<xsl:template match="compounddef" >
++ <section id="{$which}-{@id}">
++ <title>
++ <xsl:value-of select="compoundname" />
++ <xsl:if test="normalize-space(briefdescription) != ''">
++ - <xsl:apply-templates select="briefdescription" />
++ </xsl:if>
++ </title>
++ <xsl:choose>
++ <xsl:when test="normalize-space(detaileddescription) != ''">
++ <xsl:apply-templates select="detaileddescription" />
++ </xsl:when>
++ <xsl:otherwise>
++ <para />
++ </xsl:otherwise>
++ </xsl:choose>
++ <xsl:if test="sectiondef/memberdef[@kind='function' and @static='no']">
++ <variablelist>
++ <xsl:apply-templates select="sectiondef/memberdef" />
++ </variablelist>
++ </xsl:if>
++ </section>
++</xsl:template>
++</xsl:stylesheet>
--- /dev/null
--- /dev/null
++<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
++ <xsl:param name="basedir"/>
++ <xsl:output method="xml" encoding="utf-8" indent="yes"/>
++ <!-- -->
++ <!-- Template for the root so we can add a DOCTYPE -->
++ <xsl:template match="/">
++ <xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++]]></xsl:text>
++ <xsl:apply-templates select="@*|node()"/>
++ </xsl:template>
++ <!-- -->
++ <xsl:template match="@*|node()">
++ <xsl:copy>
++ <xsl:apply-templates select="@*|node()"/>
++ </xsl:copy>
++ </xsl:template>
++ <!-- -->
++ <!-- suppress existing image map areas -->
++ <xsl:template match="area"/>
++ <!-- -->
++ <xsl:template match="areaspec[area][name(..)='imageobjectco']">
++ <xsl:element name="areaspec">
++ <xsl:apply-templates select="@*"/>
++ <xsl:text>
</xsl:text>
++ <xsl:variable name="pngfile" select="../imageobject/imagedata/@fileref"/>
++ <xsl:variable name="mapfile" select="concat(substring($pngfile, 1, string-length($pngfile)-3), 'map')"/>
++ <xsl:variable name="maproot" select="document(concat($basedir, '/', $mapfile))"/>
++ <!-- -->
++ <!-- now emit the needed areas -->
++ <xsl:for-each select="area">
++ <xsl:variable name="anchor" select="."/>
++ <xsl:variable name="other" select="($maproot)//area[@href=($anchor)/@x_steal]"/>
++ <xsl:choose>
++ <xsl:when test="$other">
++ <xsl:text>	 </xsl:text>
++ <xsl:element name="area">
++ <xsl:attribute name="id">
++ <xsl:value-of select="@id"/>
++ </xsl:attribute>
++ <xsl:attribute name="linkends">
++ <xsl:value-of select="@linkends"/>
++ </xsl:attribute>
++ <xsl:attribute name="coords">
++ <xsl:value-of select="($other)/@coords"/>
++ </xsl:attribute>
++ </xsl:element>
++ </xsl:when>
++ <xsl:otherwise>
++ <xsl:text>	 </xsl:text>
++ <xsl:comment>
++ <xsl:value-of select="concat('Warning: unable to locate area tagged ', ($anchor)/@x_steal)"/>
++ </xsl:comment>
++ </xsl:otherwise>
++ </xsl:choose>
++ <xsl:text>
</xsl:text>
++ </xsl:for-each>
++ <!-- -->
++ <xsl:text>	 </xsl:text>
++ </xsl:element>
++ </xsl:template>
++</xsl:stylesheet>
--- /dev/null
--- /dev/null
++merge_mapcoords_xsl = files('merge-mapcoords.xsl')
++
++subdir('sources')
++
++custom_target(
++ 'Wayland-docbook-html',
++ command: [
++ xmlto,
++ '--skip-validation',
++ '--stringparam', 'chunker.output.encoding=UTF-8',
++ '--stringparam', 'chunk.section.depth=0',
++ '--stringparam', 'toc.section.depth=1',
++ '--stringparam', 'generate.consistent.ids=1',
++ '--stringparam', 'html.stylesheet=css/default.css',
++ '-o', '@OUTPUT@',
++ 'html',
++ '@INPUT@'
++ ],
++ input: publican_processed_main,
++ output: publican_html_dir,
++ depend_files: publican_copied_sources,
++ depends: [
++ publican_processed_targets,
++ ClientAPI_xml,
++ ServerAPI_xml,
++ ProtocolSpec_xml,
++ ProtocolInterfaces_xml
++ ],
++ build_by_default: true,
++ install: true,
++ install_dir: publican_install_prefix
++)
--- /dev/null
--- /dev/null
++<?xml version="1.0" ?>
++<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
++<xsl:output method="xml" encoding="UTF-8" indent="yes" />
++
++<xsl:template match="/">
++ <!-- insert docbook's DOCTYPE blurb -->
++ <xsl:text disable-output-escaping = "yes"><![CDATA[
++<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++ <!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++]]></xsl:text>
++
++ <section id="sect-Protocol-Interfaces">
++ <title>Interfaces</title>
++ <para>
++ The protocol includes several interfaces which are used for
++ interacting with the server. Each interface provides requests,
++ events, and errors (which are really just special events) as described
++ above. Specific compositor implementations may have their own
++ interfaces provided as extensions, but there are several which are
++ always expected to be present.
++ </para>
++
++ <para>
++ Core interfaces:
++ <variablelist>
++ <xsl:apply-templates select="protocol/interface" />
++ </variablelist>
++ </para>
++ </section>
++</xsl:template>
++
++<!-- Interfaces summary -->
++<xsl:template match="interface" >
++<varlistentry>
++ <term>
++ <link linkend="protocol-spec-{@name}">
++ <xsl:value-of select="@name" />
++ </link>
++ </term>
++ <listitem>
++ <simpara>
++ <xsl:value-of select="description/@summary" />
++ </simpara>
++ </listitem>
++</varlistentry>
++</xsl:template>
++
++</xsl:stylesheet>
++<!-- vim: set expandtab shiftwidth=2: -->
--- /dev/null
--- /dev/null
++<?xml version="1.0" ?>
++<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
++<xsl:output method="xml" encoding="UTF-8" indent="yes" />
++
++<xsl:template match="/">
++ <!-- insert docbook's DOCTYPE blurb -->
++ <xsl:text disable-output-escaping = "yes"><![CDATA[
++<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++ <!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++]]></xsl:text>
++
++ <appendix id="appe-Wayland-Protocol">
++ <title>Wayland Protocol Specification</title>
++ <xsl:apply-templates select="protocol/copyright" />
++
++ <xsl:apply-templates select="protocol/interface" />
++ </appendix>
++</xsl:template>
++
++<!-- Break text blocks separated by two new lines into paragraphs -->
++<xsl:template name="break">
++ <xsl:param name="text" />
++ <xsl:param name="linebreak" select="' '" />
++ <xsl:choose>
++ <xsl:when test="contains($text,$linebreak)">
++ <para>
++ <xsl:value-of select="substring-before($text,$linebreak)" />
++ </para>
++ <xsl:call-template name="break">
++ <xsl:with-param name="text" select="substring-after($text,$linebreak)" />
++ </xsl:call-template>
++ </xsl:when>
++ <xsl:otherwise>
++ <para><xsl:value-of select="$text" /></para>
++ </xsl:otherwise>
++ </xsl:choose>
++</xsl:template>
++
++<!-- Copyright blurb -->
++<xsl:template match="copyright">
++ <para>
++ <literallayout>
++ <xsl:value-of select="." disable-output-escaping="yes"/>
++ </literallayout>
++ </para>
++</xsl:template>
++
++<!-- Interface descriptions -->
++<xsl:template match="interface" >
++ <section id="protocol-spec-{@name}">
++ <title>
++ <xsl:value-of select="@name" />
++ <!-- only show summary if it exists -->
++ <xsl:if test="description/@summary">
++ - <xsl:value-of select="description/@summary" />
++ </xsl:if>
++ </title>
++ <xsl:call-template name="break">
++ <xsl:with-param name="text" select="description" />
++ </xsl:call-template>
++ <xsl:if test="request">
++ <section>
++ <title>Requests provided by <xsl:value-of select="@name" /></title>
++ <xsl:apply-templates select="request" />
++ </section>
++ </xsl:if>
++ <xsl:if test="event">
++ <section>
++ <title>Events provided by <xsl:value-of select="@name" /></title>
++ <xsl:apply-templates select="event" />
++ </section>
++ </xsl:if>
++ <xsl:if test="enum">
++ <section>
++ <title>Enums provided by <xsl:value-of select="@name" /></title>
++ <xsl:apply-templates select="enum" />
++ </section>
++ </xsl:if>
++ </section>
++</xsl:template>
++
++<!-- table contents for enum values -->
++<xsl:template match="entry">
++ <varlistentry>
++ <term><xsl:value-of select="@name"/></term>
++ <listitem>
++ <simpara>
++ <xsl:value-of select="@value"/>
++ <xsl:if test="@summary" >
++ - <xsl:value-of select="@summary"/>
++ </xsl:if>
++ </simpara>
++ </listitem>
++ </varlistentry>
++</xsl:template>
++
++<!-- table contents for request/event arguments -->
++<xsl:template match="arg">
++ <varlistentry>
++ <term><xsl:value-of select="@name"/></term>
++ <listitem>
++ <simpara>
++ <xsl:value-of select="@type"/>
++ <xsl:if test="@summary" >
++ - <xsl:value-of select="@summary"/>
++ </xsl:if>
++ </simpara>
++ </listitem>
++ </varlistentry>
++</xsl:template>
++
++<!-- id arguments -->
++<xsl:template match="arg[@type='object' and @interface]">
++ <varlistentry>
++ <term><xsl:value-of select="@name"/></term>
++ <listitem>
++ <simpara>
++ <link linkend="protocol-spec-{@interface}">
++ <xsl:value-of select="@interface"/>
++ </link>
++ <xsl:if test="@summary" >
++ - <xsl:value-of select="@summary"/>
++ </xsl:if>
++ </simpara>
++ </listitem>
++ </varlistentry>
++</xsl:template>
++
++<!-- new_id arguments -->
++<xsl:template match="arg[@type='new_id' and @interface]">
++ <varlistentry>
++ <term><xsl:value-of select="@name"/></term>
++ <listitem>
++ <simpara>
++ id for the new
++ <link linkend="protocol-spec-{@interface}">
++ <xsl:value-of select="@interface"/>
++ </link>
++ <xsl:if test="@summary" >
++ - <xsl:value-of select="@summary"/>
++ </xsl:if>
++ </simpara>
++ </listitem>
++ </varlistentry>
++</xsl:template>
++
++<!-- enum and bitfield arguments -->
++<xsl:template match="arg[@enum]">
++ <varlistentry>
++ <term><xsl:value-of select="@name"/></term>
++ <listitem>
++ <simpara>
++ <xsl:choose>
++ <xsl:when test="contains(@enum, '.')">
++ <link linkend="protocol-spec-{substring-before(@enum, '.')}-enum-{substring-after(@enum, '.')}">
++ <xsl:value-of select="substring-before(@enum, '.')"/>
++ <xsl:text>::</xsl:text>
++ <xsl:value-of select="substring-after(@enum, '.')"/>
++ </link>
++ </xsl:when>
++ <xsl:otherwise>
++ <link linkend="protocol-spec-{../../@name}-enum-{@enum}">
++ <xsl:value-of select="../../@name"/>
++ <xsl:text>::</xsl:text>
++ <xsl:value-of select="@enum"/>
++ </link>
++ </xsl:otherwise>
++ </xsl:choose>
++ (<xsl:value-of select="@type"/>)
++ <xsl:if test="@summary" >
++ - <xsl:value-of select="@summary"/>
++ </xsl:if>
++ </simpara>
++ </listitem>
++ </varlistentry>
++</xsl:template>
++
++<!-- Request/event list -->
++<xsl:template match="request|event">
++ <section id="protocol-spec-{../@name}-{name()}-{@name}">
++ <title>
++ <xsl:value-of select="../@name"/>::<xsl:value-of select="@name" />
++ <xsl:if test="description/@summary">
++ - <xsl:value-of select="description/@summary" />
++ </xsl:if>
++ </title>
++ <para>
++ <variablelist>
++ <xsl:apply-templates select="arg"/>
++ </variablelist>
++ </para>
++ <xsl:call-template name="break">
++ <xsl:with-param name="text" select="description" />
++ </xsl:call-template>
++ </section>
++</xsl:template>
++
++<!-- Enumeration -->
++<xsl:template match="enum">
++ <section id="protocol-spec-{../@name}-enum-{@name}">
++ <title>
++ <xsl:value-of select="../@name"/>::<xsl:value-of select="@name" />
++ <xsl:if test="@bitfield">
++ - bitfield
++ </xsl:if>
++ <xsl:if test="description/@summary">
++ - <xsl:value-of select="description/@summary" />
++ </xsl:if>
++ </title>
++ <xsl:call-template name="break">
++ <xsl:with-param name="text" select="description" />
++ </xsl:call-template>
++ <variablelist>
++ <xsl:apply-templates select="entry"/>
++ </variablelist>
++ </section>
++</xsl:template>
++
++</xsl:stylesheet>
++
++<!-- vim: set expandtab shiftwidth=2: -->
--- /dev/null
--- /dev/null
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<chapter id="chap-Wayland-Architecture">
++ <title>Wayland Architecture</title>
++ <section id="sect-Wayland-Architecture-wayland_architecture">
++ <title>X vs. Wayland Architecture</title>
++ <para>
++ A good way to understand the Wayland architecture
++ and how it is different from X is to follow an event
++ from the input device to the point where the change
++ it affects appears on screen.
++ </para>
++ <para>
++ This is where we are now with X:
++ </para>
++ <figure>
++ <title>X architecture diagram</title>
++ <mediaobjectco>
++ <imageobjectco>
++ <areaspec id="map1" units="other" otherunits="imagemap">
++ <area id="area1_1" linkends="x_flow_1" x_steal="#step_1"/>
++ <area id="area1_2" linkends="x_flow_2" x_steal="#step_2"/>
++ <area id="area1_3" linkends="x_flow_3" x_steal="#step_3"/>
++ <area id="area1_4" linkends="x_flow_4" x_steal="#step_4"/>
++ <area id="area1_5" linkends="x_flow_5" x_steal="#step_5"/>
++ <area id="area1_6" linkends="x_flow_6" x_steal="#step_6"/>
++ </areaspec>
++ <imageobject>
++ <imagedata fileref="images/x-architecture.png" format="PNG" />
++ </imageobject>
++ </imageobjectco>
++ </mediaobjectco>
++ </figure>
++ <para>
++ <orderedlist>
++ <listitem id="x_flow_1">
++ <para>
++ The kernel gets an event from an input
++ device and sends it to X through the evdev
++ input driver. The kernel does all the hard
++ work here by driving the device and
++ translating the different device specific
++ event protocols to the linux evdev input
++ event standard.
++ </para>
++ </listitem>
++ <listitem id="x_flow_2">
++ <para>
++ The X server determines which window the
++ event affects and sends it to the clients
++ that have selected for the event in question
++ on that window. The X server doesn't
++ actually know how to do this right, since
++ the window location on screen is controlled
++ by the compositor and may be transformed in
++ a number of ways that the X server doesn't
++ understand (scaled down, rotated, wobbling,
++ etc).
++ </para>
++ </listitem>
++ <listitem id="x_flow_3">
++ <para>
++ The client looks at the event and decides
++ what to do. Often the UI will have to change
++ in response to the event - perhaps a check
++ box was clicked or the pointer entered a
++ button that must be highlighted. Thus the
++ client sends a rendering request back to the
++ X server.
++ </para>
++ </listitem>
++ <listitem id="x_flow_4">
++ <para>
++ When the X server receives the rendering
++ request, it sends it to the driver to let it
++ program the hardware to do the rendering.
++ The X server also calculates the bounding
++ region of the rendering, and sends that to
++ the compositor as a damage event.
++ </para>
++ </listitem>
++ <listitem id="x_flow_5">
++ <para>
++ The damage event tells the compositor that
++ something changed in the window and that it
++ has to recomposite the part of the screen
++ where that window is visible. The compositor
++ is responsible for rendering the entire
++ screen contents based on its scenegraph and
++ the contents of the X windows. Yet, it has
++ to go through the X server to render this.
++ </para>
++ </listitem>
++ <listitem id="x_flow_6">
++ <para>
++ The X server receives the rendering requests
++ from the compositor and either copies the
++ compositor back buffer to the front buffer
++ or does a pageflip. In the general case, the
++ X server has to do this step so it can
++ account for overlapping windows, which may
++ require clipping and determine whether or
++ not it can page flip. However, for a
++ compositor, which is always fullscreen, this
++ is another unnecessary context switch.
++ </para>
++ </listitem>
++ </orderedlist>
++ </para>
++ <para>
++ As suggested above, there are a few problems with this
++ approach. The X server doesn't have the information to
++ decide which window should receive the event, nor can it
++ transform the screen coordinates to window-local
++ coordinates. And even though X has handed responsibility for
++ the final painting of the screen to the compositing manager,
++ X still controls the front buffer and modesetting. Most of
++ the complexity that the X server used to handle is now
++ available in the kernel or self contained libraries (KMS,
++ evdev, mesa, fontconfig, freetype, cairo, Qt etc). In
++ general, the X server is now just a middle man that
++ introduces an extra step between applications and the
++ compositor and an extra step between the compositor and the
++ hardware.
++ </para>
++ <para>
++ In Wayland the compositor is the display server. We transfer
++ the control of KMS and evdev to the compositor. The Wayland
++ protocol lets the compositor send the input events directly
++ to the clients and lets the client send the damage event
++ directly to the compositor:
++ </para>
++ <figure>
++ <title>Wayland architecture diagram</title>
++ <mediaobjectco>
++ <imageobjectco>
++ <areaspec id="mapB" units="other" otherunits="imagemap">
++ <area id="areaB_1" linkends="wayland_flow_1" x_steal="#step_1"/>
++ <area id="areaB_2" linkends="wayland_flow_2" x_steal="#step_2"/>
++ <area id="areaB_3" linkends="wayland_flow_3" x_steal="#step_3"/>
++ <area id="areaB_4" linkends="wayland_flow_4" x_steal="#step_4"/>
++ </areaspec>
++ <imageobject>
++ <imagedata fileref="images/wayland-architecture.png" format="PNG" />
++ </imageobject>
++ </imageobjectco>
++ </mediaobjectco>
++ </figure>
++ <para>
++ <orderedlist>
++ <listitem id="wayland_flow_1">
++ <para>
++ The kernel gets an event and sends
++ it to the compositor. This
++ is similar to the X case, which is
++ great, since we get to reuse all the
++ input drivers in the kernel.
++ </para>
++ </listitem>
++ <listitem id="wayland_flow_2">
++ <para>
++ The compositor looks through its
++ scenegraph to determine which window
++ should receive the event. The
++ scenegraph corresponds to what's on
++ screen and the compositor
++ understands the transformations that
++ it may have applied to the elements
++ in the scenegraph. Thus, the
++ compositor can pick the right window
++ and transform the screen coordinates
++ to window-local coordinates, by
++ applying the inverse
++ transformations. The types of
++ transformation that can be applied
++ to a window is only restricted to
++ what the compositor can do, as long
++ as it can compute the inverse
++ transformation for the input events.
++ </para>
++ </listitem>
++ <listitem id="wayland_flow_3">
++ <para>
++ As in the X case, when the client
++ receives the event, it updates the
++ UI in response. But in the Wayland
++ case, the rendering happens in the
++ client, and the client just sends a
++ request to the compositor to
++ indicate the region that was
++ updated.
++ </para>
++ </listitem>
++ <listitem id="wayland_flow_4">
++ <para>
++ The compositor collects damage
++ requests from its clients and then
++ recomposites the screen. The
++ compositor can then directly issue
++ an ioctl to schedule a pageflip with
++ KMS.
++ </para>
++ </listitem>
++
++
++ </orderedlist>
++ </para>
++ </section>
++ <section id="sect-Wayland-Architecture-wayland_rendering">
++ <title>Wayland Rendering</title>
++ <para>
++ One of the details I left out in the above overview
++ is how clients actually render under Wayland. By
++ removing the X server from the picture we also
++ removed the mechanism by which X clients typically
++ render. But there's another mechanism that we're
++ already using with DRI2 under X: direct rendering.
++ With direct rendering, the client and the server
++ share a video memory buffer. The client links to a
++ rendering library such as OpenGL that knows how to
++ program the hardware and renders directly into the
++ buffer. The compositor in turn can take the buffer
++ and use it as a texture when it composites the
++ desktop. After the initial setup, the client only
++ needs to tell the compositor which buffer to use and
++ when and where it has rendered new content into it.
++ </para>
++
++ <para>
++ This leaves an application with two ways to update its window contents:
++ </para>
++ <para>
++ <orderedlist>
++ <listitem>
++ <para>
++ Render the new content into a new buffer and tell the compositor
++ to use that instead of the old buffer. The application can
++ allocate a new buffer every time it needs to update the window
++ contents or it can keep two (or more) buffers around and cycle
++ between them. The buffer management is entirely under
++ application control.
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ Render the new content into the buffer that it previously
++ told the compositor to to use. While it's possible to just
++ render directly into the buffer shared with the compositor,
++ this might race with the compositor. What can happen is that
++ repainting the window contents could be interrupted by the
++ compositor repainting the desktop. If the application gets
++ interrupted just after clearing the window but before
++ rendering the contents, the compositor will texture from a
++ blank buffer. The result is that the application window will
++ flicker between a blank window or half-rendered content. The
++ traditional way to avoid this is to render the new content
++ into a back buffer and then copy from there into the
++ compositor surface. The back buffer can be allocated on the
++ fly and just big enough to hold the new content, or the
++ application can keep a buffer around. Again, this is under
++ application control.
++ </para>
++ </listitem>
++ </orderedlist>
++ </para>
++ <para>
++ In either case, the application must tell the compositor
++ which area of the surface holds new contents. When the
++ application renders directly to the shared buffer, the
++ compositor needs to be noticed that there is new content.
++ But also when exchanging buffers, the compositor doesn't
++ assume anything changed, and needs a request from the
++ application before it will repaint the desktop. The idea
++ that even if an application passes a new buffer to the
++ compositor, only a small part of the buffer may be
++ different, like a blinking cursor or a spinner.
++ </para>
++ </section>
++ <section id="sect-Wayland-Architecture-wayland_hw_enabling">
++ <title>Hardware Enabling for Wayland</title>
++ <para>
++ Typically, hardware enabling includes modesetting/display
++ and EGL/GLES2. On top of that Wayland needs a way to share
++ buffers efficiently between processes. There are two sides
++ to that, the client side and the server side.
++ </para>
++ <para>
++ On the client side we've defined a Wayland EGL platform. In
++ the EGL model, that consists of the native types
++ (EGLNativeDisplayType, EGLNativeWindowType and
++ EGLNativePixmapType) and a way to create those types. In
++ other words, it's the glue code that binds the EGL stack and
++ its buffer sharing mechanism to the generic Wayland API. The
++ EGL stack is expected to provide an implementation of the
++ Wayland EGL platform. The full API is in the wayland-egl.h
++ header. The open source implementation in the mesa EGL stack
++ is in wayland-egl.c and platform_wayland.c.
++ </para>
++ <para>
++ Under the hood, the EGL stack is expected to define a
++ vendor-specific protocol extension that lets the client side
++ EGL stack communicate buffer details with the compositor in
++ order to share buffers. The point of the wayland-egl.h API
++ is to abstract that away and just let the client create an
++ EGLSurface for a Wayland surface and start rendering. The
++ open source stack uses the drm Wayland extension, which lets
++ the client discover the drm device to use and authenticate
++ and then share drm (GEM) buffers with the compositor.
++ </para>
++ <para>
++ The server side of Wayland is the compositor and core UX for
++ the vertical, typically integrating task switcher, app
++ launcher, lock screen in one monolithic application. The
++ server runs on top of a modesetting API (kernel modesetting,
++ OpenWF Display or similar) and composites the final UI using
++ a mix of EGL/GLES2 compositor and hardware overlays if
++ available. Enabling modesetting, EGL/GLES2 and overlays is
++ something that should be part of standard hardware bringup.
++ The extra requirement for Wayland enabling is the
++ EGL_WL_bind_wayland_display extension that lets the
++ compositor create an EGLImage from a generic Wayland shared
++ buffer. It's similar to the EGL_KHR_image_pixmap extension
++ to create an EGLImage from an X pixmap.
++ </para>
++ <para>
++ The extension has a setup step where you have to bind the
++ EGL display to a Wayland display. Then as the compositor
++ receives generic Wayland buffers from the clients (typically
++ when the client calls eglSwapBuffers), it will be able to
++ pass the struct wl_buffer pointer to eglCreateImageKHR as
++ the EGLClientBuffer argument and with EGL_WAYLAND_BUFFER_WL
++ as the target. This will create an EGLImage, which can then
++ be used by the compositor as a texture or passed to the
++ modesetting code to use as an overlay plane. Again, this is
++ implemented by the vendor specific protocol extension, which
++ on the server side will receive the driver specific details
++ about the shared buffer and turn that into an EGL image when
++ the user calls eglCreateImageKHR.
++ </para>
++ </section>
++</chapter>
--- /dev/null
--- /dev/null
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE authorgroup PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<authorgroup>
++ <author>
++ <firstname>Kristian</firstname>
++ <surname>Høgsberg</surname>
++ <affiliation>
++ <orgname>Intel Corporation</orgname>
++ </affiliation>
++ <email>krh@bitplanet.net</email>
++ </author>
++</authorgroup>
++
--- /dev/null
--- /dev/null
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<bookinfo id="book-Wayland-Wayland">
++ <title>Wayland</title>
++ <subtitle>The Wayland Protocol</subtitle>
++ <productname>Documentation</productname>
++ <productnumber>0.1</productnumber>
++ <edition>1</edition>
++ <pubsnumber>0</pubsnumber>
++ <abstract>
++ <para>
++ Wayland is a protocol for a compositor to talk to
++ its clients as well as a C library implementation of
++ that protocol. The compositor can be a standalone
++ display server running on Linux kernel modesetting
++ and evdev input devices, an X application, or a
++ Wayland client itself. The clients can be
++ traditional applications, X servers (rootless or
++ fullscreen) or other display servers.
++ </para>
++ </abstract>
++ <corpauthor>
++ <inlinemediaobject>
++ <imageobject>
++ <imagedata fileref="images/wayland.png" format="PNG" />
++ </imageobject>
++ <textobject>
++ <phrase>
++ Wayland logo
++ </phrase>
++ </textobject>
++ </inlinemediaobject>
++ </corpauthor>
++
++ <legalnotice lang="en-US">
++ <para>
++ Copyright <trademark class="copyright"></trademark> &YEAR; &HOLDER;
++ </para>
++
++ <para>
++ Permission is hereby granted, free of charge, to any person obtaining a
++ copy of this software and associated documentation files (the "Software"),
++ to deal in the Software without restriction, including without limitation
++ the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ and/or sell copies of the Software, and to permit persons to whom the
++ Software is furnished to do so, subject to the following conditions:
++ </para>
++
++ <para>
++ The above copyright notice and this permission notice (including the next
++ paragraph) shall be included in all copies or substantial portions of the
++ Software.
++ </para>
++
++ <para>
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ </para>
++ </legalnotice>
++
++
++ <xi:include href="Author_Group.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++</bookinfo>
--- /dev/null
--- /dev/null
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++ <!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++ <!ENTITY doxygen SYSTEM "ClientAPI.xml">
++%BOOK_ENTITIES;
++]>
++<appendix id="sect-Library-Client">
++ <title>Client API</title>
++ <section><title>Introduction</title>
++ <para>
++ The open-source reference implementation of Wayland protocol is
++ split in two C libraries, libwayland-client and <link
++ linkend="sect-Library-Server">libwayland-server</link>. Their main
++ responsibility is to handle the Inter-process communication
++ (<emphasis>IPC</emphasis>) with each other, therefore guaranteeing
++ the protocol objects marshaling and messages synchronization.
++ </para>
++ <para>
++ A client uses libwayland-client to communicate with one or more
++ wayland servers. A <link
++ linkend="Client-classwl__display">wl_display</link> object is
++ created and manages each open connection to a server. At least one
++ <link linkend="Client-classwl__event__queue">wl_event_queue</link>
++ object is created for each wl_display, this holds events as they
++ are received from the server until they can be
++ processed. Multi-threading is supported by creating an additional
++ wl_event_queue for each additional thread, each object can have
++ it's events placed in a particular queue, so potentially a
++ different thread could be made to handle the events for each
++ object created.
++ </para>
++ <para>
++ Though some convenience functions are provided, libwayland-client
++ is designed to allow the calling code to wait for events, so that
++ different polling mechanisms can be used. A file descriptor is
++ provided, when it becomes ready for reading the calling code can
++ ask libwayland-client to read the available events from it into
++ the wl_event_queue objects.
++ </para>
++ <para>
++ The library only provides low-level access to the wayland objects.
++ Each object created by the client is represented by a <link
++ linkend="Client-classwl__proxy">wl_proxy</link> object that this
++ library creates. This includes the id that is actually
++ communicated over the socket to the server, a void* data pointer
++ that is intended to point at a client's representation of the
++ object, and a pointer to a static <link
++ linkend="Client-structwl__interface">wl_interface</link> object,
++ which is generated from the xml and identifies the object's class
++ and can be used for introspection into the messages and events.
++ </para>
++ <para>
++ Messages are sent by calling wl_proxy_marshal. This will write a
++ message to the socket, by using the message id and the
++ wl_interface to identify the types of each argument and convert
++ them into stream format. Most software will call type-safe
++ wrappers generated from the xml description of the <link
++ linkend="appe-Wayland-Protocol">Wayland protocols</link>. For
++ instance the C header file generated from the xml defines the
++ following inline function to transmit the <link
++ linkend="protocol-spec-wl_surface-request-attach">wl_surface::attach</link>
++ message:
++ </para>
++ <programlisting>static inline void
++wl_surface_attach(struct wl_surface *wl_surface, struct wl_buffer *buffer, int32_t x, int32_t y)
++{
++ wl_proxy_marshal((struct wl_proxy *) wl_surface, WL_SURFACE_ATTACH, buffer, x, y);
++}</programlisting>
++ <para>
++ Events (messages from the server) are handled by calling a
++ "dispatcher" callback the client stores in the wl_proxy for each
++ event. A language binding for a string-based interpreter, such as
++ CPython, might have a dispatcher that uses the event name from the
++ wl_interface to identify the function to call. The default
++ dispatcher uses the message id number to index an array of
++ functions pointers, called a wl_listener, and the wl_interface to
++ convert data from the stream into arguments to the function. The
++ C header file generated from the xml defines a per-class structure
++ that forces the function pointers to be of the correct type, for
++ instance the <link
++ linkend="protocol-spec-wl_surface-event-enter">wl_surface::enter</link>
++ event defines this pointer in the wl_surface_listener object:
++ </para>
++ <programlisting>struct wl_surface_listener {
++ void (*enter)(void *data, struct wl_surface *, struct wl_output *);
++ ...
++}</programlisting>
++ <para>
++ </para>
++ </section>
++ &doxygen;
++</appendix>
--- /dev/null
--- /dev/null
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<chapter id="chap-Compositors">
++ <title>Types of Compositors</title>
++
++ <para>
++ Compositors come in different types, depending on which
++ role they play in the overall architecture of the OS.
++ For instance, a
++ <link linkend="sect-Compositors-System-Compositor">system compositor</link>
++ can be used for booting the system, handling multiple user switching, a
++ possible console terminal emulator and so forth. A different compositor, a
++ <link linkend="sect-Compositors-Session-Compositor">session compositor</link>
++ would provide the actual desktop environment. There are many ways for
++ different types of compositors to co-exist.
++ </para>
++ <para>
++ In this section, we introduce three types of Wayland compositors relying
++ on <link linkend="sect-Library-Server">libwayland-server</link>.
++ </para>
++
++ <section id="sect-Compositors-System-Compositor">
++ <title>System Compositor</title>
++ <para>
++ A system compositor can run from early boot until shutdown.
++ It effectively replaces the kernel vt system, and can tie in
++ with the systems graphical boot setup and multiseat support.
++ </para>
++ <para>
++ A system compositor can host different types of session
++ compositors, and let us switch between multiple sessions
++ (fast user switching, or secure/personal desktop switching).
++ </para>
++ <para>
++ A linux implementation of a system compositor will typically
++ use libudev, egl, kms, evdev and cairo.
++ </para>
++ <para>
++ For fullscreen clients, the system compositor can reprogram the
++ video scanout address to read directly from the client provided
++ buffer.
++ </para>
++ </section>
++ <section id="sect-Compositors-Session-Compositor">
++ <title>Session Compositor</title>
++ <para>
++ A session compositor is responsible for a single user session.
++ If a system compositor is present, the session compositor will
++ run nested under the system compositor. Nesting is feasible because
++ the protocol is asynchronous; roundtrips would be too expensive
++ when nesting is involved. If no system compositor is present, a
++ session compositor can run directly on the hardware.
++ </para>
++ <para>
++ X applications can continue working under a session compositor
++ by means of a root-less X server that is activated on demand.
++ </para>
++ <para>
++ Possible examples for session compositors include
++ <itemizedlist>
++ <listitem>
++ <para>
++ gnome-shell
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ moblin
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ kwin
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ kmscon
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ rdp session
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ Weston with X11 or Wayland backend is a session compositor nested
++ in another session compositor.
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ fullscreen X session under Wayland
++ </para>
++ </listitem>
++ </itemizedlist>
++ </para>
++ </section>
++ <section id="sect-Compositors-Embedding-Compositor">
++ <title>Embedding Compositor</title>
++ <para>
++ X11 lets clients embed windows from other clients, or lets clients
++ copy pixmap contents rendered by another client into their window.
++ This is often used for applets in a panel, browser plugins and similar.
++ Wayland doesn't directly allow this, but clients can communicate GEM
++ buffer names out-of-band, for example, using D-Bus, or command line
++ arguments when the panel launches the applet. Another option is to
++ use a nested Wayland instance. For this, the Wayland server will have
++ to be a library that the host application links to. The host
++ application will then pass the Wayland server socket name to the
++ embedded application, and will need to implement the Wayland
++ compositor interface. The host application composites the client
++ surfaces as part of it's window, that is, in the web page or in the
++ panel. The benefit of nesting the Wayland server is that it provides
++ the requests the embedded client needs to inform the host about buffer
++ updates and a mechanism for forwarding input events from the host
++ application.
++ </para>
++ <para>
++ An example for this kind of setup is firefox embedding the flash
++ player as a kind of special-purpose compositor.
++ </para>
++ </section>
++</chapter>
--- /dev/null
--- /dev/null
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
++"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++
++<preface>
++ <title>Preface</title>
++
++ <para>
++ This document describes the (i) Wayland architecture, (ii) Wayland model of
++ operation and (iii) its library API. Also, the Wayland protocol specification is shown
++ in the Appendix. This document is aimed primarily at Wayland developers and
++ those looking to program with it; it does not cover application development.
++ </para>
++ <para>
++ There have been many contributors to this document and since this is only the
++ first edition many errors are expected to be found. We appreciate
++ corrections.
++ </para>
++ <literallayout>
++Yours,
++
++ the Wayland open-source community
++ November 2012
++ </literallayout>
++</preface>
--- /dev/null
--- /dev/null
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<chapter id="chap-Introduction">
++ <title>Introduction</title>
++ <section id="sect-Motivation">
++ <title>Motivation</title>
++ <para>
++ Most Linux and Unix-based systems rely on the X Window System (or
++ simply <emphasis>X</emphasis>) as the low-level protocol for building
++ bitmap graphics interfaces. On these systems, the X stack has grown to
++ encompass functionality arguably belonging in client libraries,
++ helper libraries, or the host operating system kernel. Support for
++ things like PCI resource management, display configuration management,
++ direct rendering, and memory management has been integrated into the X
++ stack, imposing limitations like limited support for standalone
++ applications, duplication in other projects (e.g. the Linux fb layer
++ or the DirectFB project), and high levels of complexity for systems
++ combining multiple elements (for example radeon memory map handling
++ between the fb driver and X driver, or VT switching).
++ </para>
++ <para>
++ Moreover, X has grown to incorporate modern features like offscreen
++ rendering and scene composition, but subject to the limitations of the
++ X architecture. For example, the X implementation of composition adds
++ additional context switches and makes things like input redirection
++ difficult.
++ </para>
++ <mediaobject>
++ <imageobject>
++ <imagedata fileref="images/x-architecture.png" format="PNG" />
++ </imageobject>
++ <textobject>
++ <phrase>
++ X architecture diagram
++ </phrase>
++ </textobject>
++ </mediaobject>
++ <para>
++ The diagram above illustrates the central role of the X server and
++ compositor in operations, and the steps required to get contents on to
++ the screen.
++ </para>
++ <para>
++ Over time, X developers came to understand the shortcomings of this
++ approach and worked to split things up. Over the past several years,
++ a lot of functionality has moved out of the X server and into
++ client-side libraries or kernel drivers. One of the first components
++ to move out was font rendering, with freetype and fontconfig providing
++ an alternative to the core X fonts. Direct rendering OpenGL as a
++ graphics driver in a client side library went through some iterations,
++ ending up as DRI2, which abstracted most of the direct rendering
++ buffer management from client code. Then cairo came along and provided
++ a modern 2D rendering library independent of X, and compositing
++ managers took over control of the rendering of the desktop as toolkits
++ like GTK+ and Qt moved away from using X APIs for rendering. Recently,
++ memory and display management have moved to the Linux kernel, further
++ reducing the scope of X and its driver stack. The end result is a
++ highly modular graphics stack.
++ </para>
++
++ </section>
++
++ <section id="sect-Compositing-manager-display-server">
++ <title>The compositing manager as the display server</title>
++ <para>
++ Wayland is a new display server and compositing protocol, and Weston
++ is the implementation of this protocol which builds on top of all the
++ components above. We are trying to distill out the functionality in
++ the X server that is still used by the modern Linux desktop. This
++ turns out to be not a whole lot. Applications can allocate their own
++ off-screen buffers and render their window contents directly, using
++ hardware accelerated libraries like libGL, or high quality software
++ implementations like those found in Cairo. In the end, what’s needed
++ is a way to present the resulting window surface for display, and a
++ way to receive and arbitrate input among multiple clients. This is
++ what Wayland provides, by piecing together the components already in
++ the eco-system in a slightly different way.
++ </para>
++ <para>
++ X will always be relevant, in the same way Fortran compilers and VRML
++ browsers are, but it’s time that we think about moving it out of the
++ critical path and provide it as an optional component for legacy
++ applications.
++ </para>
++ <para>
++ Overall, the philosophy of Wayland is to provide clients with a way to
++ manage windows and how their contents is displayed. Rendering is left
++ to clients, and system wide memory management interfaces are used to
++ pass buffer handles between clients and the compositing manager.
++ </para>
++ <mediaobject>
++ <imageobject>
++ <imagedata fileref="images/wayland-architecture.png" format="PNG" />
++ </imageobject>
++ <textobject>
++ <phrase>
++ Wayland architecture diagram
++ </phrase>
++ </textobject>
++ </mediaobject>
++ <para>
++ The figure above illustrates how Wayland clients interact with a
++ Wayland server. Note that window management and composition are
++ handled entirely in the server, significantly reducing complexity
++ while marginally improving performance through reduced context
++ switching. The resulting system is easier to build and extend than a
++ similar X system, because often changes need only be made in one
++ place. Or in the case of protocol extensions, two (rather than 3 or 4
++ in the X case where window management and/or composition handling may
++ also need to be updated).
++ </para>
++ </section>
++</chapter>
--- /dev/null
--- /dev/null
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
++"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++
++<preface>
++ <title>Acknowledgments</title>
++
++ <para>
++ TODO: Kristian has to fill up this with one or two paragraphs and a small
++ "thank you": http://en.wikipedia.org/wiki/Preface
++ </para>
++ <literallayout>
++Best,
++
++ Kristian Høgsberg
++ </literallayout>
++</preface>
--- /dev/null
--- /dev/null
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<chapter id="chap-Protocol">
++ <title>Wayland Protocol and Model of Operation</title>
++ <section id="sect-Protocol-Basic-Principles">
++ <title>Basic Principles</title>
++ <para>
++ The Wayland protocol is an asynchronous object oriented protocol. All
++ requests are method invocations on some object. The requests include
++ an object ID that uniquely identifies an object on the server. Each
++ object implements an interface and the requests include an opcode that
++ identifies which method in the interface to invoke.
++ </para>
++ <para>
++ The protocol is message-based. A message sent by a client to the server
++ is called request. A message from the server to a client is called event.
++ A message has a number of arguments, each of which has a certain type (see
++ <xref linkend="sect-Protocol-Wire-Format"/> for a list of argument types).
++ </para>
++ <para>
++ Additionally, the protocol can specify <type>enum</type>s which associate
++ names to specific numeric enumeration values. These are primarily just
++ descriptive in nature: at the wire format level enums are just integers.
++ But they also serve a secondary purpose to enhance type safety or
++ otherwise add context for use in language bindings or other such code.
++ This latter usage is only supported so long as code written before these
++ attributes were introduced still works after; in other words, adding an
++ enum should not break API, otherwise it puts backwards compatibility at
++ risk.
++ </para>
++ <para>
++ <type>enum</type>s can be defined as just a set of integers, or as
++ bitfields. This is specified via the <type>bitfield</type> boolean
++ attribute in the <type>enum</type> definition. If this attribute is true,
++ the enum is intended to be accessed primarily using bitwise operations,
++ for example when arbitrarily many choices of the enum can be ORed
++ together; if it is false, or the attribute is omitted, then the enum
++ arguments are a just a sequence of numerical values.
++ </para>
++ <para>
++ The <type>enum</type> attribute can be used on either <type>uint</type>
++ or <type>int</type> arguments, however if the <type>enum</type> is
++ defined as a <type>bitfield</type>, it can only be used on
++ <type>uint</type> args.
++ </para>
++ <para>
++ The server sends back events to the client, each event is emitted from
++ an object. Events can be error conditions. The event includes the
++ object ID and the event opcode, from which the client can determine
++ the type of event. Events are generated both in response to requests
++ (in which case the request and the event constitutes a round trip) or
++ spontaneously when the server state changes.
++ </para>
++ <para>
++ <itemizedlist>
++ <listitem>
++ <para>
++ State is broadcast on connect, events are sent
++ out when state changes. Clients must listen for
++ these changes and cache the state.
++ There is no need (or mechanism) to query server state.
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ The server will broadcast the presence of a number of global objects,
++ which in turn will broadcast their current state.
++ </para>
++ </listitem>
++ </itemizedlist>
++ </para>
++ </section>
++ <section id="sect-Protocol-Code-Generation">
++ <title>Code Generation</title>
++ <para>
++ The interfaces, requests and events are defined in
++ <filename>protocol/wayland.xml</filename>.
++ This xml is used to generate the function prototypes that can be used by
++ clients and compositors.
++ </para>
++ <para>
++ The protocol entry points are generated as inline functions which just
++ wrap the <function>wl_proxy_*</function> functions. The inline functions aren't
++ part of the library ABI and language bindings should generate their
++ own stubs for the protocol entry points from the xml.
++ </para>
++ </section>
++ <section id="sect-Protocol-Wire-Format">
++ <title>Wire Format</title>
++ <para>
++ The protocol is sent over a UNIX domain stream socket, where the endpoint
++ usually is named <systemitem class="service">wayland-0</systemitem>
++ (although it can be changed via <emphasis>WAYLAND_DISPLAY</emphasis>
++ in the environment). Beginning in Wayland 1.15, implementations can
++ optionally support server socket endpoints located at arbitrary
++ locations in the filesystem by setting <emphasis>WAYLAND_DISPLAY</emphasis>
++ to the absolute path at which the server endpoint listens.
++ </para>
++ <para>
++ Every message is structured as 32-bit words; values are represented in the
++ host's byte-order. The message header has 2 words in it:
++ <itemizedlist>
++ <listitem>
++ <para>
++ The first word is the sender's object ID (32-bit).
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ The second has 2 parts of 16-bit. The upper 16-bits are the message
++ size in bytes, starting at the header (i.e. it has a minimum value of 8).The lower is the request/event opcode.
++ </para>
++ </listitem>
++ </itemizedlist>
++ The payload describes the request/event arguments. Every argument is always
++ aligned to 32-bits. Where padding is required, the value of padding bytes is
++ undefined. There is no prefix that describes the type, but it is
++ inferred implicitly from the xml specification.
++ </para>
++ <para>
++
++ The representation of argument types are as follows:
++ <variablelist>
++ <varlistentry>
++ <term>int</term>
++ <term>uint</term>
++ <listitem>
++ <para>
++ The value is the 32-bit value of the signed/unsigned
++ int.
++ </para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term>fixed</term>
++ <listitem>
++ <para>
++ Signed 24.8 decimal numbers. It is a signed decimal type which
++ offers a sign bit, 23 bits of integer precision and 8 bits of
++ decimal precision. This is exposed as an opaque struct with
++ conversion helpers to and from double and int on the C API side.
++ </para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term>string</term>
++ <listitem>
++ <para>
++ Starts with an unsigned 32-bit length (including null terminator),
++ followed by the string contents, including terminating null byte,
++ then padding to a 32-bit boundary. A null value is represented
++ with a length of 0.
++ </para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term>object</term>
++ <listitem>
++ <para>
++ 32-bit object ID. A null value is represented with an ID of 0.
++ </para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term>new_id</term>
++ <listitem>
++ <para>
++ The 32-bit object ID. Generally, the interface used for the new
++ object is inferred from the xml, but in the case where it's not
++ specified, a new_id is preceded by a <code>string</code> specifying
++ the interface name, and a <code>uint</code> specifying the version.
++ </para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term>array</term>
++ <listitem>
++ <para>
++ Starts with 32-bit array size in bytes, followed by the array
++ contents verbatim, and finally padding to a 32-bit boundary.
++ </para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term>fd</term>
++ <listitem>
++ <para>
++ The file descriptor is not stored in the message buffer, but in
++ the ancillary data of the UNIX domain socket message (msg_control).
++ </para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </para>
++ <para>
++ The protocol does not specify the exact position of the ancillary data
++ in the stream, except that the order of file descriptors is the same as
++ the order of messages and <code>fd</code> arguments within messages on
++ the wire.
++ </para>
++ <para>
++ In particular, it means that any byte of the stream, even the message
++ header, may carry the ancillary data with file descriptors.
++ </para>
++ <para>
++ Clients and compositors should queue incoming data until they have
++ whole messages to process, as file descriptors may arrive earlier
++ or later than the corresponding data bytes.
++ </para>
++ </section>
++ <xi:include href="ProtocolInterfaces.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
++ <section id="sect-Protocol-Versioning">
++ <title>Versioning</title>
++ <para>
++ Every interface is versioned and every protocol object implements a
++ particular version of its interface. For global objects, the maximum
++ version supported by the server is advertised with the global and the
++ actual version of the created protocol object is determined by the
++ version argument passed to wl_registry.bind(). For objects that are
++ not globals, their version is inferred from the object that created
++ them.
++ </para>
++ <para>
++ In order to keep things sane, this has a few implications for
++ interface versions:
++ <itemizedlist>
++ <listitem>
++ <para>
++ The object creation hierarchy must be a tree. Otherwise,
++ inferring object versions from the parent object becomes a much
++ more difficult to properly track.
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ When the version of an interface increases, so does the version
++ of its parent (recursively until you get to a global interface)
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ A global interface's version number acts like a counter for all
++ of its child interfaces. Whenever a child interface gets
++ modified, the global parent's interface version number also
++ increases (see above). The child interface then takes on the
++ same version number as the new version of its parent global
++ interface.
++ </para>
++ </listitem>
++ </itemizedlist>
++ </para>
++ <para>
++ To illustrate the above, consider the wl_compositor interface. It
++ has two children, wl_surface and wl_region. As of wayland version
++ 1.2, wl_surface and wl_compositor are both at version 3. If
++ something is added to the wl_region interface, both wl_region and
++ wl_compositor will get bumpped to version 4. If, afterwards,
++ wl_surface is changed, both wl_compositor and wl_surface will be at
++ version 5. In this way the global interface version is used as a
++ sort of "counter" for all of its child interfaces. This makes it
++ very simple to know the version of the child given the version of its
++ parent. The child is at the highest possible interface version that
++ is less than or equal to its parent's version.
++ </para>
++ <para>
++ It is worth noting a particular exception to the above versioning
++ scheme. The wl_display (and, by extension, wl_registry) interface
++ cannot change because it is the core protocol object and its version
++ is never advertised nor is there a mechanism to request a different
++ version.
++ </para>
++ </section>
++ <section id="sect-Protocol-Connect-Time">
++ <title>Connect Time</title>
++ <para>
++ There is no fixed connection setup information, the server emits
++ multiple events at connect time, to indicate the presence and
++ properties of global objects: outputs, compositor, input devices.
++ </para>
++ </section>
++ <section id="sect-Protocol-Security-and-Authentication">
++ <title>Security and Authentication</title>
++ <para>
++ <itemizedlist>
++ <listitem>
++ <para>
++ mostly about access to underlying buffers, need new drm auth
++ mechanism (the grant-to ioctl idea), need to check the cmd stream?
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ getting the server socket depends on the compositor type, could
++ be a system wide name, through fd passing on the session dbus.
++ or the client is forked by the compositor and the fd is
++ already opened.
++ </para>
++ </listitem>
++ </itemizedlist>
++ </para>
++ </section>
++ <section id="sect-Protocol-Creating-Objects">
++ <title>Creating Objects</title>
++ <para>
++ Each object has a unique ID. The IDs are allocated by the entity
++ creating the object (either client or server). IDs allocated by the
++ client are in the range [1, 0xfeffffff] while IDs allocated by the
++ server are in the range [0xff000000, 0xffffffff]. The 0 ID is
++ reserved to represent a null or non-existent object.
++
++ For efficiency purposes, the IDs are densely packed in the sense that
++ the ID N will not be used until N-1 has been used. Any ID allocation
++ algorithm that does not maintain this property is incompatible with
++ the implementation in libwayland.
++ </para>
++ </section>
++ <section id="sect-Protocol-Compositor">
++ <title>Compositor</title>
++ <para>
++ The compositor is a global object, advertised at connect time.
++ </para>
++ <para>
++ See <xref linkend="protocol-spec-wl_compositor"/> for the
++ protocol description.
++ </para>
++ </section>
++ <section id="sect-Protocol-Surface">
++ <title>Surfaces</title>
++ <para>
++ A surface manages a rectangular grid of pixels that clients create
++ for displaying their content to the screen. Clients don't know
++ the global position of their surfaces, and cannot access other
++ clients' surfaces.
++ </para>
++ <para>
++ Once the client has finished writing pixels, it 'commits' the
++ buffer; this permits the compositor to access the buffer and read
++ the pixels. When the compositor is finished, it releases the
++ buffer back to the client.
++ </para>
++ <para>
++ See <xref linkend="protocol-spec-wl_surface"/> for the protocol
++ description.
++ </para>
++ </section>
++ <section id="sect-Protocol-Input">
++ <title>Input</title>
++ <para>
++ A seat represents a group of input devices including mice,
++ keyboards and touchscreens. It has a keyboard and pointer
++ focus. Seats are global objects. Pointer events are delivered
++ in surface-local coordinates.
++ </para>
++ <para>
++ The compositor maintains an implicit grab when a button is
++ pressed, to ensure that the corresponding button release
++ event gets delivered to the same surface. But there is no way
++ for clients to take an explicit grab. Instead, surfaces can
++ be mapped as 'popup', which combines transient window semantics
++ with a pointer grab.
++ </para>
++ <para>
++ To avoid race conditions, input events that are likely to
++ trigger further requests (such as button presses, key events,
++ pointer motions) carry serial numbers, and requests such as
++ wl_surface.set_popup require that the serial number of the
++ triggering event is specified. The server maintains a
++ monotonically increasing counter for these serial numbers.
++ </para>
++ <para>
++ Input events also carry timestamps with millisecond granularity.
++ Their base is undefined, so they can't be compared against
++ system time (as obtained with clock_gettime or gettimeofday).
++ They can be compared with each other though, and for instance
++ be used to identify sequences of button presses as double
++ or triple clicks.
++ </para>
++ <para>
++ See <xref linkend="protocol-spec-wl_seat"/> for the
++ protocol description.
++ </para>
++ <para>
++ Talk about:
++
++ <itemizedlist>
++ <listitem>
++ <para>
++ keyboard map, change events
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ xkb on Wayland
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ multi pointer Wayland
++ </para>
++ </listitem>
++ </itemizedlist>
++ </para>
++ <para>
++ A surface can change the pointer image when the surface is the pointer
++ focus of the input device. Wayland doesn't automatically change the
++ pointer image when a pointer enters a surface, but expects the
++ application to set the cursor it wants in response to the pointer
++ focus and motion events. The rationale is that a client has to manage
++ changing pointer images for UI elements within the surface in response
++ to motion events anyway, so we'll make that the only mechanism for
++ setting or changing the pointer image. If the server receives a request
++ to set the pointer image after the surface loses pointer focus, the
++ request is ignored. To the client this will look like it successfully
++ set the pointer image.
++ </para>
++ <para>
++ Setting the pointer image to NULL causes the cursor to be hidden.
++ </para>
++ <para>
++ The compositor will revert the pointer image back to a default image
++ when no surface has the pointer focus for that device.
++ </para>
++ <para>
++ What if the pointer moves from one window which has set a special
++ pointer image to a surface that doesn't set an image in response to
++ the motion event? The new surface will be stuck with the special
++ pointer image. We can't just revert the pointer image on leaving a
++ surface, since if we immediately enter a surface that sets a different
++ image, the image will flicker. If a client does not set a pointer image
++ when the pointer enters a surface, the pointer stays with the image set
++ by the last surface that changed it, possibly even hidden. Such a client
++ is likely just broken.
++ </para>
++ </section>
++ <section id="sect-Protocol-Output">
++ <title>Output</title>
++ <para>
++ An output is a global object, advertised at connect time or as it
++ comes and goes.
++ </para>
++ <para>
++ See <xref linkend="protocol-spec-wl_output"/> for the protocol
++ description.
++ </para>
++ <para>
++ </para>
++ <itemizedlist>
++ <listitem>
++ <para>
++ laid out in a big (compositor) coordinate system
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ basically xrandr over Wayland
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ geometry needs position in compositor coordinate system
++ </para>
++ </listitem>
++ <listitem>
++ <para>
++ events to advertise available modes, requests to move and change
++ modes
++ </para>
++ </listitem>
++ </itemizedlist>
++ </section>
++ <section id="sect-Protocol-data-sharing">
++ <title>Data sharing between clients</title>
++ <para>
++ The Wayland protocol provides clients a mechanism for sharing
++ data that allows the implementation of copy-paste and
++ drag-and-drop. The client providing the data creates a
++ <function>wl_data_source</function> object and the clients
++ obtaining the data will see it as <function>wl_data_offer</function>
++ object. This interface allows the clients to agree on a mutually
++ supported mime type and transfer the data via a file descriptor
++ that is passed through the protocol.
++ </para>
++ <para>
++ The next section explains the negotiation between data source and
++ data offer objects. <xref linkend="sect-Protocol-data-sharing-devices"/>
++ explains how these objects are created and passed to different
++ clients using the <function>wl_data_device</function> interface
++ that implements copy-paste and drag-and-drop support.
++ </para>
++ <para>
++ See <xref linkend="protocol-spec-wl_data_offer"/>,
++ <xref linkend="protocol-spec-wl_data_source"/>,
++ <xref linkend="protocol-spec-wl_data_device"/> and
++ <xref linkend="protocol-spec-wl_data_device_manager"/> for
++ protocol descriptions.
++ </para>
++ <para>
++ MIME is defined in RFC's 2045-2049. A
++ <ulink url="https://www.iana.org/assignments/media-types/media-types.xhtml">
++ registry of MIME types</ulink> is maintained by the Internet Assigned
++ Numbers Authority (IANA).
++ </para>
++ <section>
++ <title>Data negotiation</title>
++ <para>
++ A client providing data to other clients will create a <function>wl_data_source</function>
++ object and advertise the mime types for the formats it supports for
++ that data through the <function>wl_data_source.offer</function>
++ request. On the receiving end, the data offer object will generate one
++ <function>wl_data_offer.offer</function> event for each supported mime
++ type.
++ </para>
++ <para>
++ The actual data transfer happens when the receiving client sends a
++ <function>wl_data_offer.receive</function> request. This request takes
++ a mime type and a file descriptor as arguments. This request will generate a
++ <function>wl_data_source.send</function> event on the sending client
++ with the same arguments, and the latter client is expected to write its
++ data to the given file descriptor using the chosen mime type.
++ </para>
++ </section>
++ <section id="sect-Protocol-data-sharing-devices">
++ <title>Data devices</title>
++ <para>
++ Data devices glue data sources and offers together. A data device is
++ associated with a <function>wl_seat</function> and is obtained by the clients using the
++ <function>wl_data_device_manager</function> factory object, which is also responsible for
++ creating data sources.
++ </para>
++ <para>
++ Clients are informed of new data offers through the
++ <function>wl_data_device.data_offer</function> event. After this
++ event is generated the data offer will advertise the available mime
++ types. New data offers are introduced prior to their use for
++ copy-paste or drag-and-drop.
++ </para>
++ <section>
++ <title>Selection</title>
++ <para>
++ Each data device has a selection data source. Clients create a data
++ source object using the device manager and may set it as the
++ current selection for a given data device. Whenever the current
++ selection changes, the client with keyboard focus receives a
++ <function>wl_data_device.selection</function> event. This event is
++ also generated on a client immediately before it receives keyboard
++ focus.
++ </para>
++ <para>
++ The data offer is introduced with
++ <function>wl_data_device.data_offer</function> event before the
++ selection event.
++ </para>
++ </section>
++ <section>
++ <title>Drag and Drop</title>
++ <para>
++ A drag-and-drop operation is started using the
++ <function>wl_data_device.start_drag</function> request. This
++ requests causes a pointer grab that will generate enter, motion and
++ leave events on the data device. A data source is supplied as
++ argument to start_drag, and data offers associated with it are
++ supplied to clients surfaces under the pointer in the
++ <function>wl_data_device.enter</function> event. The data offer
++ is introduced to the client prior to the enter event with the
++ <function>wl_data_device.data_offer</function> event.
++ </para>
++ <para>
++ Clients are expected to provide feedback to the data sending client
++ by calling the <function>wl_data_offer.accept</function> request with
++ a mime type it accepts. If none of the advertised mime types is
++ supported by the receiving client, it should supply NULL to the
++ accept request. The accept request causes the sending client to
++ receive a <function>wl_data_source.target</function> event with the
++ chosen mime type.
++ </para>
++ <para>
++ When the drag ends, the receiving client receives a
++ <function>wl_data_device.drop</function> event at which it is expected
++ to transfer the data using the
++ <function>wl_data_offer.receive</function> request.
++ </para>
++ </section>
++ </section>
++ </section>
++</chapter>
--- /dev/null
--- /dev/null
++<revhistory>
++ <revision>
++ <revnumber>1-0</revnumber>
++ <authorinitials>krh</authorinitials>
++ <revremark>Initial version</revremark>
++ </revision>
++</revhistory>
--- /dev/null
--- /dev/null
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++ <!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++ <!ENTITY doxygen SYSTEM "ServerAPI.xml">
++%BOOK_ENTITIES;
++]>
++<appendix id="sect-Library-Server">
++ <title>Server API</title>
++ <section><title>Introduction</title>
++ <para>
++ The open-source reference implementation of Wayland protocol is
++ split in two C libraries, <link
++ linkend="sect-Library-Client">libwayland-client</link> and
++ libwayland-server. Their main responsibility is to handle the
++ Inter-process communication (<emphasis>IPC</emphasis>) with each
++ other, therefore guaranteeing the protocol objects marshaling and
++ messages synchronization.
++ </para>
++ <para>
++ The server library is designed to work much like libwayland-client,
++ although it is considerably complicated due to the server needing
++ to support multiple versions of the protocol. It is best to learn
++ libwayland-client first.
++ </para>
++ <para>
++ Each open socket to a client is represented by a <link
++ linkend="Server-structwl__client">wl_client</link>. The equivalent
++ of the <link linkend="Client-classwl__proxy">wl_proxy</link> that
++ libwayland-client uses to represent an object is <link
++ linkend="Server-structwl__resource">wl_resource</link> for
++ client-created objects, and <link
++ linkend="Server-structwl__global">wl_global</link> for objects
++ created by the server.
++ </para>
++ <para>
++ Often a server is also a client for another Wayland server, and
++ thus must link with both libwayland-client and libwayland-server.
++ This produces some type name conflicts (such as the <link
++ linkend="Client-classwl__display">client wl_display</link> and
++ <link linkend="Server-structwl__display">server wl_display</link>,
++ but the duplicate-but-not-the-same types are opaque, and accessed
++ only inside the correct library where it came from. Naturally that
++ means that the program writer needs to always know if a pointer to
++ a wl_display is for the server or client side and use the
++ corresponding functions.
++ </para>
++ </section>
++ &doxygen;
++</appendix>
--- /dev/null
--- /dev/null
++<!ENTITY PRODUCT "Documentation">
++<!ENTITY BOOKID "Wayland">
++<!ENTITY YEAR "2012">
++<!ENTITY HOLDER "Kristian Høgsberg, Intel Corporation">
--- /dev/null
--- /dev/null
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<book>
++ <xi:include href="Book_Info.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++ <xi:include href="Foreword.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++ <xi:include href="Preface.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++ <xi:include href="Introduction.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++ <xi:include href="Compositors.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++ <xi:include href="Architecture.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++ <xi:include href="Protocol.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++ <xi:include href="Xwayland.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++ <xi:include href="ProtocolSpec.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++ <xi:include href="Client.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
++ <xi:include href="Server.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
++</book>
--- /dev/null
--- /dev/null
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<chapter id="chap-X11-Application-Support">
++ <title>X11 Application Support</title>
++ <section id="sect-X11-Application-Support-introduction">
++ <title>Introduction</title>
++ <para>
++ Being able to run existing X11 applications is crucial for the adoption
++ of Wayland, especially on desktops, as there will always be X11
++ applications that have not been or cannot be converted into Wayland
++ applications, and throwing them all away would be prohibitive.
++ Therefore a Wayland compositor often needs to support running X11
++ applications.
++ </para>
++ <para>
++ X11 and Wayland are different enough that there is no "simple" way to
++ translate between them. Most of X11 is uninteresting to a Wayland
++ compositor. That, combined with the gigantic implementation effort needed
++ to support X11, makes it intractable to just write X11 support directly in
++ a Wayland compositor. The implementation would be nothing short of a
++ real X11 server.
++ </para>
++ <para>
++ Therefore, Wayland compositors should use Xwayland, the X11 server that
++ lives in the Xorg server source code repository and shares most of the
++ implementation with the Xorg server. Xwayland is a complete X11 server,
++ just like Xorg is, but instead of driving the displays and opening input
++ devices, it acts as a Wayland client. The rest of this chapter talks
++ about how Xwayland works.
++ </para>
++ <para>
++ For integration and architecture reasons, while Xwayland is a Wayland
++ client of the Wayland compositor, the Wayland compositor is an X11 client
++ of Xwayland. This circular dependency requires special care from the
++ Wayland compositor.
++ </para>
++ </section>
++ <section id="sect-X11-Application-Support-two-modes">
++ <title>Two Modes for Foreign Windows</title>
++ <para>
++ In general, windows from a foreign window system can be presented in one
++ of two ways: rootless and rootful (not rootless).
++ </para>
++ <para>
++ In rootful mode, the foreign window system as a whole is represented as a
++ window (or more) of its own. You have a native window, inside which all
++ the foreign windows are. The advantage of this approach in Xwayland's
++ case is that you can run your favourite X11 window manager to manage your
++ X11 applications. The disadvantage is that the foreign windows do not
++ integrate with the native desktop. Therefore this mode is not usually
++ used.
++ </para>
++ <para>
++ In rootless mode, each foreign window is a first-class resident among the
++ native windows. Foreign windows are not confined inside a native window
++ but act as if they were native windows. The advantage is that one can
++ freely stack and mix native and foreign windows, which is not possible in
++ rootful mode. The disadvantage is that this mode is harder to implement
++ and fundamental differences in window systems may prevent some things
++ from working. With rootless Xwayland, the Wayland compositor must take
++ the role as the X11 window manager, and one cannot use any other X11
++ window manager in its place.
++ </para>
++ <para>
++ This chapter concentrates on the rootless mode, and ignores the rootful
++ mode.
++ </para>
++ </section>
++ <section id="sect-X11-Application-Support-architecture">
++ <title>Architecture</title>
++ <para>
++ A Wayland compositor usually takes care of launching Xwayland.
++ Xwayland works in cooperation with a Wayland compositor as follows:
++ </para>
++ <figure>
++ <title>Xwayland architecture diagram</title>
++ <mediaobjectco>
++ <imageobjectco>
++ <imageobject>
++ <imagedata fileref="images/xwayland-architecture.png" format="PNG" />
++ </imageobject>
++ </imageobjectco>
++ </mediaobjectco>
++ </figure>
++ <para>
++ An X11 application connects to Xwayland just like it would connect to any
++ X server. Xwayland processes all the X11 requests. On the other end,
++ Xwayland is a Wayland client that connects to the Wayland compositor.
++ </para>
++ <para>
++ The X11 window manager (XWM) is an integral part of the Wayland
++ compositor. XWM uses the usual X11 window management protocol to manage
++ all X11 windows in Xwayland. Most importantly, XWM acts as a bridge
++ between Xwayland window state and the Wayland compositor's window manager
++ (WWM). This way WWM can manage all windows, both native Wayland and X11
++ (Xwayland) windows. This is very important for a coherent user
++ experience.
++ </para>
++ <para>
++ Since Xwayland uses Wayland for input and output, it does not have any
++ use for the device drivers that Xorg uses. None of the xf86-video-* or
++ xf86-input-* modules are used. There also is no configuration file for
++ the Xwayland server. For optional hardware accelerated rendering,
++ Xwayland uses GLAMOR.
++ </para>
++ <para>
++ A Wayland compositor usually spawns only one Xwayland instance. This is
++ because many X11 applications assume they can communicate with other X11
++ applications through the X server, and this requires a shared X server
++ instance. This also means that Xwayland does not protect nor isolate X11
++ clients from each other, unless the Wayland compositor specifically
++ chooses to break the X11 client intercommunications by spawning
++ application specific Xwayland instances. X11 clients are naturally
++ isolated from Wayland clients.
++ </para>
++ <para>
++ Xwayland compatibility compared to a native X server will probably never
++ reach 100%. Desktop environment (DE) components, specifically X11 window
++ managers, are practically never supported. An X11 window manager would
++ not know about native Wayland windows, so it could manage only X11
++ windows. On the other hand, there must be an XWM that reserves the
++ exclusive window manager role so that the Wayland compositor could show
++ the X11 windows appropriately. For other DE components, like pagers and
++ panels, adding the necessary interfaces to support them in WWM through XWM
++ is often considered not worthwhile.
++ </para>
++ </section>
++ <section id="sect-X11-Application-Support-xwm">
++ <title>X Window Manager (XWM)</title>
++ <para>
++ From the X11 point of view, the X window manager (XWM) living inside a
++ Wayland compositor is just like any other window manager. The difference
++ is mostly in which process it resides in, and the few extra conventions
++ in the X11 protocol to support Wayland window management (WWM)
++ specifically.
++ </para>
++ <para>
++ There are two separate asynchronous communication channels between
++ Xwayland and a Wayland compositor: one uses the Wayland protocol, and the
++ other one, solely for XWM, uses X11 protocol. This setting demands great
++ care from the XWM implementation to avoid (random) deadlocks with
++ Xwayland. It is often nearly impossible to prove that synchronous or
++ blocking X11 calls from XWM cannot cause a deadlock, and therefore it is
++ strongly recommended to make all X11 communications asynchronous. All
++ Wayland communications are already asynchronous by design.
++ </para>
++ <section id="sect-X11-Application-Support-xwm-window-identification">
++ <title>Window identification</title>
++ <para>
++ In Xwayland, an X11 window may have a corresponding wl_surface object
++ in Wayland. The wl_surface object is used for input and output: it is
++ referenced by input events and used to provide the X11 window content
++ to the Wayland compositor. The X11 window and the wl_surface live in
++ different protocol streams, and they need to be matched for XWM to do
++ its job.
++ </para>
++ <para>
++ When Xwayland creates a wl_surface on Wayland, it will also send an X11
++ ClientMessage of type atom "WL_SURFACE_ID" to the X11 window carrying
++ the wl_surface Wayland object ID as the first 32-bit data element. This
++ is how XWM can associate a wl_surface with an X11 window. Note that
++ the request to create a wl_surface and the ID message may arrive in any
++ order in the Wayland compositor.
++ </para>
++ </section>
++ </section>
++</chapter>
--- /dev/null
--- /dev/null
++/*headings*/
++h1, h2, h3, h4, h5, h6,
++div.producttitle,
++div.subtitle,
++div.author div.author,
++div.translator div.translator,
++div.othercredit div.othercredit,
++div.editor div.editor,
++div.contrib div.contrib,
++.title,
++.titlepage .edition,
++.titlepage .releaseinfo {
++ color: #336699;
++}
--- /dev/null
--- /dev/null
++* {
++ widows: 4 !important;
++ orphans: 4 !important;
++}
++
++body, h1, h2, h3, h4, h5, h6, pre, li, div {
++ line-height: 1.29em;
++}
++
++body {
++ background-color: white;
++ margin:0 auto;
++ font-family: "liberation sans", "Myriad ", "Bitstream Vera Sans", "Lucida Grande", "Luxi Sans", "Trebuchet MS", helvetica, verdana, arial, sans-serif;
++ font-size: 14px;
++ max-width: 770px;
++ color: black;
++}
++
++body.toc_embeded {
++ /*for web hosting system only*/
++ margin-left: 300px;
++}
++
++object.toc, iframe.toc {
++ /*for web hosting system only*/
++ border-style: none;
++ position: fixed;
++ width: 290px;
++ height: 99.99%;
++ top: 0;
++ left: 0;
++ z-index: 100;
++ border-style: none;
++ border-right:1px solid #999;
++}
++
++/* Hide web menu */
++
++body.notoc {
++ margin-left: 3em;
++}
++
++iframe.notoc {
++ border-style:none;
++ border: none;
++ padding: 0px;
++ position:fixed;
++ width: 21px;
++ height: 29px;
++ top: 0px;
++ left:0;
++ overflow: hidden;
++ margin: 0px;
++ margin-left: -3px;
++}
++/* End hide web menu */
++
++/* desktop styles */
++body.desktop {
++ margin-left: 26em;
++}
++
++body.desktop .book > .toc {
++ display:block;
++ width:24em;
++ height:99.99%;
++ position:fixed;
++ overflow:auto;
++ top:0px;
++ left:0px;
++/* padding-left:1em; */
++ background-color:#EEEEEE;
++ font-size: 12px;
++}
++
++body.pdf {
++ max-width: 100%;
++}
++
++.toc {
++ line-height:1.35em;
++}
++
++.toc .glossary,
++.toc .chapter, .toc .appendix {
++ margin-top:1em;
++}
++
++.toc .part {
++ margin-top:1em;
++ display:block;
++}
++
++span.glossary,
++span.appendix {
++ display:block;
++ margin-top:0.5em;
++}
++
++div {
++ padding-top:0px;
++}
++
++div.section {
++ page-break-inside: avoid;
++}
++
++p, div.para {
++ padding-top: 0px;
++ margin-top: 1em;
++ padding-bottom: 0px;
++ margin-bottom: 1em;
++}
++
++div.formalpara {
++ padding-top: 0px;
++ margin-top: 1em;
++ padding-bottom: 0px;
++ margin-bottom: 1em;
++}
++
++.varlistentry div.para {
++ page-break-before: avoid;
++
++}
++
++/*Links*/
++a {
++ outline: none;
++}
++
++a:link {
++ text-decoration: none;
++ border-bottom: 1px dotted ;
++ color:#3366cc;
++}
++
++body.pdf a:link {
++ word-wrap: break-word;
++}
++
++a:visited {
++ text-decoration:none;
++ border-bottom: 1px dotted ;
++ color:#003366;
++}
++
++div.longdesc-link {
++ float:right;
++ color:#999;
++}
++
++.toc a, .qandaset a {
++ font-weight:normal;
++ border:none;
++}
++
++.toc a:hover, .qandaset a:hover
++{
++ border-bottom: 1px dotted;
++}
++
++/*headings*/
++h1, h2, h3, h4, h5, h6 {
++ color: #336699;
++ margin-top: 0px;
++ margin-bottom: 0px;
++ background-color: transparent;
++ margin-bottom: 0px;
++ margin-top: 20px;
++ page-break-inside: avoid;
++ page-break-after: avoid;
++ word-wrap: break-word;
++}
++
++h1 {
++ font-size: 22px;
++}
++
++.titlepage h1.title {
++ text-align:left;
++}
++
++.book > .titlepage h1.title {
++ text-align: center;
++}
++
++.article > .titlepage h1.title,
++.article > .titlepage h2.title {
++ text-align: center;
++}
++
++.set .titlepage > div > div > h1.title {
++ text-align: center;
++}
++
++.part > .titlepage h1.title {
++ text-align: center;
++ font-size: 24px;
++}
++
++div.producttitle {
++ margin-top: 0px;
++ margin-bottom: 20px;
++ font-size: 48px;
++ font-weight: bold;
++/* background: #003d6e url(../images/h1-bg.png) top left repeat-x; */
++ color: #336699;
++ text-align: center;
++ padding-top: 12px;
++}
++
++.titlepage .corpauthor {
++ margin-top: 1em;
++ text-align: center;
++}
++
++.section h1.title {
++ font-size: 18px;
++ padding: 0px;
++ color: #336699;
++ text-align: left;
++ background: white;
++}
++
++h2 {
++ font-size: 20px;
++ margin-top: 30px;
++}
++
++
++.book div.subtitle, .book h2.subtitle, .book h3.subtitle {
++ margin-top: 1em;
++ margin-bottom: 1em;
++ font-size: 18px;
++ text-align: center;
++}
++
++div.subtitle {
++ color: #336699;
++ font-weight: bold;
++}
++
++h1.legalnotice {
++ font-size: 24px;
++}
++
++.preface > div > div > div > h2.title,
++.preface > div > div > div > h1.title {
++ margin-top: 1em;
++ font-size: 24px;
++}
++
++.appendix h2 {
++ font-size: 24px;
++}
++
++
++
++h3 {
++ font-size: 14px;
++ padding-top:0px;
++ padding-bottom: 0px;
++ margin-bottom: 0px;
++}
++h4 {
++ font-size: 14px;
++ padding-top:0px;
++ padding-bottom:0px;
++}
++
++h5 {
++ font-size: 14px;
++}
++
++h6 {
++ font-size: 14px;
++ margin-bottom: 0px;
++}
++
++.abstract h6 {
++ margin-top:1em;
++ margin-bottom:.5em;
++ font-size: 24px;
++}
++
++.index > div > div > div > h2.title {
++ font-size: 24px;
++}
++
++.chapter > div > div > div > h2.title {
++ font-size: 24px;
++}
++
++.section > div > div > div > h2.title {
++ font-size: 21px;
++ page-break-inside: avoid;
++ page-break-before: avoid;
++ page-break-after: avoid;
++}
++
++.section > div > div > div > h3.title {
++ font-size: 17px;
++}
++
++/*element rules*/
++hr {
++ border-collapse: collapse;
++ border-style:none;
++ border-top: 1px dotted #ccc;
++ width:100%;
++}
++
++/* web site rules */
++ul.languages, .languages li {
++ display:inline;
++ padding:0px;
++}
++
++.languages li a {
++ padding:0px .5em;
++ text-decoration: none;
++}
++
++.languages li p, .languages li div.para {
++ display:inline;
++}
++
++.languages li a:link, .languages li a:visited {
++ color:#444;
++}
++
++.languages li a:hover, .languages li a:focus, .languages li a:active {
++ color:black;
++}
++
++ul.languages {
++ display:block;
++ background-color:#eee;
++ padding:.5em;
++}
++
++/*supporting stylesheets*/
++
++/*unique to the webpage only*/
++.books {
++ position:relative;
++}
++
++.versions li {
++ width:100%;
++ clear:both;
++ display:block;
++}
++
++a.version {
++ font-size: 20px;
++ text-decoration:none;
++ width:100%;
++ display:block;
++ padding:1em 0px .2em 0px;
++ clear:both;
++}
++
++a.version:before {
++ content:"Version";
++ font-size: smaller;
++}
++
++a.version:visited, a.version:link {
++ color:#666;
++}
++
++a.version:focus, a.version:hover {
++ color:black;
++}
++
++.books {
++ display:block;
++ position:relative;
++ clear:both;
++ width:100%;
++}
++
++.books li {
++ display:block;
++ width:200px;
++ float:left;
++ position:relative;
++ clear: none ;
++}
++
++.books .html {
++ width:170px;
++ display:block;
++}
++
++.books .pdf {
++ position:absolute;
++ left:170px;
++ top:0px;
++ font-size: smaller;
++}
++
++.books .pdf:link, .books .pdf:visited {
++ color:#555;
++}
++
++.books .pdf:hover, .books .pdf:focus {
++ color:#000;
++}
++
++.books li a {
++ text-decoration:none;
++}
++
++.books li a:hover {
++ color:black;
++}
++
++/*products*/
++.products li {
++ display: block;
++ width:300px;
++ float:left;
++}
++
++.products li a {
++ width:300px;
++ padding:.5em 0px;
++}
++
++.products ul {
++ clear:both;
++}
++
++/*revision history*/
++.revhistory {
++ display:block;
++}
++
++.revhistory table {
++ background-color:transparent;
++ border-color:#fff;
++ padding:0px;
++ margin: 0;
++ border-collapse:collapse;
++ border-style:none;
++}
++
++.revhistory td {
++ text-align :left;
++ padding:0px;
++ border: none;
++ border-top: 1px solid #fff;
++ font-weight: bold;
++}
++
++.revhistory .simplelist td {
++ font-weight: normal;
++}
++
++.revhistory .simplelist {
++ margin-bottom: 1.5em;
++ margin-left: 1em;
++}
++
++.revhistory table th {
++ display: none;
++}
++
++
++/*credits*/
++.authorgroup div {
++ clear:both;
++ text-align: center;
++}
++
++div.author div.author,
++div.translator div.translator,
++div.othercredit div.othercredit,
++div.editor div.editor,
++div.contrib div.contrib {
++ margin: 0px;
++ padding: 0px;
++ margin-top: 12px;
++ font-size: 14px;
++ font-weight: bold;
++ color: #336699;
++}
++
++div.editedby {
++ margin-top: 15px;
++ margin-bottom: -0.8em;
++}
++
++div.authorgroup .author,
++div.authorgroup.editor,
++div.authorgroup.translator,
++div.authorgroup.othercredit,
++div.authorgroup.contrib {
++ display: block;
++ font-size: 14px;
++ page-break-inside: avoid;
++}
++
++.revhistory .author {
++ display: inline;
++}
++
++.othercredit h3 {
++ padding-top: 1em;
++}
++
++
++.othercredit {
++ margin:0px;
++ padding:0px;
++}
++
++.releaseinfo {
++ clear: both;
++}
++
++.copyright {
++ margin-top: 1em;
++}
++
++/* qanda sets */
++.answer {
++ margin-bottom:1em;
++ border-bottom:1px dotted #ccc;
++}
++
++.qandaset .toc {
++ border-bottom:1px dotted #ccc;
++}
++
++.question {
++ font-weight:bold;
++}
++
++.answer .data, .question .data {
++ padding-left: 2.6em;
++}
++
++.answer .label, .question .label {
++ float:left;
++ font-weight:bold;
++}
++
++/* inline syntax highlighting */
++.perl_Alert {
++ color: #0000ff;
++}
++
++.perl_BaseN {
++ color: #007f00;
++}
++
++.perl_BString {
++ color: #5C3566;
++}
++
++.perl_Char {
++ color: #ff00ff;
++}
++
++.perl_Comment {
++ color: #888888;
++}
++
++
++.perl_DataType {
++ color: #0000ff;
++}
++
++
++.perl_DecVal {
++ color: #00007f;
++}
++
++
++.perl_Error {
++ color: #ff0000;
++}
++
++
++.perl_Float {
++ color: #00007f;
++}
++
++
++.perl_Function {
++ color: #007f00;
++}
++
++
++.perl_IString {
++ color: #5C3566;
++}
++
++
++.perl_Keyword {
++ color: #002F5D;
++}
++
++
++.perl_Operator {
++ color: #ffa500;
++}
++
++
++.perl_Others {
++ color: #b03060;
++}
++
++
++.perl_RegionMarker {
++ color: #96b9ff;
++}
++
++
++.perl_Reserved {
++ color: #9b30ff;
++}
++
++
++.perl_String {
++ color: #5C3566;
++}
++
++
++.perl_Variable {
++ color: #0000ff;
++}
++
++
++.perl_Warning {
++ color: #0000ff;
++}
++
++/*Lists*/
++ul {
++ list-style-image: url("../images/dot.png");
++ list-style-type: circle;
++ padding-left: 1.6em;
++}
++
++ul ul {
++ list-style-image: url("../images/dot2.png");
++ list-style-type: circle;
++}
++
++ol.1 {
++ list-style-type: decimal;
++}
++
++ol.a,
++ol ol {
++ list-style-type: lower-alpha;
++}
++
++ol.i {
++ list-style-type: lower-roman;
++}
++ol.A {
++ list-style-type: upper-alpha;
++}
++
++ol.I {
++ list-style-type: upper-roman;
++}
++
++dt {
++ font-weight:bold;
++ margin-bottom:0px;
++ padding-bottom:0px;
++}
++
++dd {
++ margin:0px;
++ margin-left:2em;
++ padding-top:0px;
++}
++
++li {
++ padding-top: 0px;
++ margin-top: 0px;
++ padding-bottom: 0px;
++/* margin-bottom: 16px; */
++}
++
++/*images*/
++img {
++ display:block;
++ margin: 2em 0;
++ max-width: 100%;
++}
++
++.inlinemediaobject,
++.inlinemediaobject img,
++.inlinemediaobject object {
++ display:inline;
++ margin:0px;
++ overflow: hidden;
++}
++
++.figure {
++ margin-top: 1em;
++ width: 100%;
++}
++
++.figure img,
++.mediaobject img {
++ display:block;
++ margin: 0em;
++ page-break-inside: avoid;
++}
++
++.figure .title {
++ margin-bottom:2em;
++ padding:0px;
++}
++
++/*document modes*/
++.confidential {
++ background-color:#900;
++ color:White;
++ padding:.5em .5em;
++ text-transform:uppercase;
++ text-align:center;
++}
++
++.longdesc-link {
++ display:none;
++}
++
++.longdesc {
++ display:none;
++}
++
++.prompt {
++ padding:0px .3em;
++}
++
++/*user interface styles*/
++.screen .replaceable {
++}
++
++.guibutton, .guilabel {
++ font-family: "liberation mono", "bitstream vera mono", "dejavu mono", monospace;
++ font-weight: bold;
++}
++
++.example {
++ background-color: #ffffff;
++ border-left: 3px solid #aaaaaa;
++ padding-top: 1px;
++ padding-bottom: 0.1em;
++ padding-left: 1em;
++}
++
++.equation {
++ border-left: 3px solid #aaaaaa;
++ background-color: #ffffff;
++ padding-top: 1px;
++ padding-bottom: 0.1em;
++ padding-left: 1em;
++}
++
++.equation-contents {
++ margin-left: 4em;
++}
++
++div.title {
++ margin-bottom: 1em;
++ font-weight: 14px;
++ font-weight: bold;
++ color: #336699;
++ page-break-inside: avoid;
++ page-break-after: avoid;
++ word-wrap: break-word;
++}
++
++.example-contents {
++ background-color: #ffffff;
++}
++
++.example-contents .para {
++/* padding: 10px;*/
++}
++
++/*terminal/console text*/
++.computeroutput,
++.option {
++ font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace;
++ font-weight:bold;
++}
++
++.replaceable {
++ font-style: italic;
++}
++
++.command, .filename, .keycap, .classname, .literal {
++ font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace;
++ font-weight:bold;
++}
++
++/* no bold in toc */
++.toc * {
++ font-weight: inherit;
++}
++
++.toc H1 {
++ font-weight: bold;
++}
++
++
++div.programlisting {
++ white-space: pre-wrap; /* css-3 */
++ white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
++ white-space: -pre-wrap; /* Opera 4-6 */
++ white-space: -o-pre-wrap; /* Opera 7 */
++ word-wrap: break-word; /* Internet Explorer 5.5+ */
++}
++
++pre {
++ font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace;
++ display:block;
++ background-color: #f5f5f5;
++ color: #000000;
++/* border: 1px solid #aaaaaa; */
++ margin-bottom: 1em;
++ padding:.5em 1em;
++ white-space: pre-wrap; /* css-3 */
++ white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
++ white-space: -pre-wrap; /* Opera 4-6 */
++ white-space: -o-pre-wrap; /* Opera 7 */
++ word-wrap: break-word; /* Internet Explorer 5.5+ */
++ font-size: 0.9em;
++ border-style:none;
++ box-shadow: 0 2px 5px #AAAAAA inset;
++ -moz-box-shadow: 0 2px 5px #AAAAAA inset;
++ -webkit-box-shadow: 0 2px 5px #AAAAAA inset;
++ -o-box-shadow: 0 2px 5px #AAAAAA inset;
++}
++
++body.pdf pre {
++ border: 1px solid #AAAAAA;
++ box-shadow: none;
++ -moz-box-shadow: none;
++ -webkit-box-shadow: none;
++ -o-box-shadow: none;
++}
++
++
++pre .replaceable,
++pre .keycap {
++}
++
++code {
++ font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace;
++ white-space: pre-wrap;
++ word-wrap: break-word;
++ font-weight:bold;
++}
++
++.parameter code {
++ display: inline;
++ white-space: pre-wrap; /* css-3 */
++ white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
++ white-space: -pre-wrap; /* Opera 4-6 */
++ white-space: -o-pre-wrap; /* Opera 7 */
++ word-wrap: break-word; /* Internet Explorer 5.5+ */
++}
++
++code.email {
++ font-weight: normal;
++ font-family: "liberation sans", "Myriad ", "Bitstream Vera Sans", "Lucida Grande", "Luxi Sans", "Trebuchet MS", helvetica, verdana, arial, sans-serif;
++
++}
++
++/*Notifications*/
++div.warning:before {
++ content:url(../images/warning.png);
++ padding-left: 5px;
++}
++
++div.note:before {
++ content:url(../images/note.png);
++ padding-left: 5px;
++}
++
++div.important:before {
++ content:url(../images/important.png);
++ padding-left: 5px;
++}
++
++div.warning, div.note, div.important {
++ color: black;
++ margin: 0px;
++ padding: 0px;
++ background: none;
++ background-color: white;
++ margin-bottom: 1em;
++ border-bottom: 1px solid #aaaaaa;
++ page-break-inside: avoid;
++}
++
++div.admonition_header p {
++ margin: 0px;
++ padding: 0px;
++ color: #eeeeec;
++ padding-top: 0px;
++ padding-bottom: 0px;
++ height: 1.4em;
++ line-height: 1.4em;
++ font-size: 17px;
++ display:inline;
++}
++
++div.admonition_header {
++ background-origin:content-box;
++ clear: both;
++ margin: 0px;
++ padding: 0px;
++ margin-top: -40px;
++ padding-left: 58px;
++ line-height: 1.0px;
++ font-size: 1.0px;
++}
++
++div.warning div.admonition_header {
++ background: url(../images/red.png) top left repeat-x;
++ background-color: #590000;
++ background: -webkit-linear-gradient(#a40000,#590000);
++ background: linear-gradient(#a40000,#590000);
++}
++
++div.note div.admonition_header {
++ background: url(../images/green.png) top right repeat-x;
++ background-color: #597800;
++ background: -webkit-linear-gradient(#769f00,#597800);
++ background: linear-gradient(#769f00,#597800);
++}
++
++div.important div.admonition_header {
++ background: url(../images/yellow.png) top right repeat-x;
++ background-color: #a6710f;
++ background: -webkit-linear-gradient(#d08e13,#a6710f);
++ background: linear-gradient(#d08e13,#a6710f);
++}
++
++div.warning p:first-child,
++div.warning div.para:first-child,
++div.note p:first-child,
++div.note div.para:first-child,
++div.important p:first-child,
++div.important div.para:first-child {
++ padding: 0px;
++ margin: 0px;
++}
++
++div.admonition {
++ border: none;
++ border-left: 1px solid #aaaaaa;
++ border-right: 1px solid #aaaaaa;
++ padding:0px;
++ margin:0px;
++ padding-top: 1.5em;
++ padding-bottom: 1em;
++ padding-left: 2em;
++ padding-right: 1em;
++ background-color: #eeeeec;
++ -moz-border-radius: 0px;
++ -webkit-border-radius: 0px;
++ border-radius: 0px;
++}
++
++/*Page Title*/
++#title {
++ display:block;
++ height:45px;
++ padding-bottom:1em;
++ margin:0px;
++}
++
++#title a.left{
++ display:inline;
++ border:none;
++}
++
++#title a.left img{
++ border:none;
++ float:left;
++ margin:0px;
++ margin-top:.7em;
++}
++
++#title a.right {
++ padding-bottom:1em;
++}
++
++#title a.right img {
++ border:none;
++ float:right;
++ margin:0px;
++ margin-top:.7em;
++}
++
++/*Table*/
++div.table {
++/* page-break-inside: avoid; */
++}
++
++table {
++ border: 1px solid #444;
++ width:100%;
++ border-collapse:collapse;
++ table-layout: fixed;
++ word-wrap: break-word;
++}
++
++table.blockquote,
++table.simplelist,
++.calloutlist table {
++ border-style: none;
++}
++
++table th {
++ text-align:left;
++ background-color:#6699cc;
++ padding:.3em .5em;
++ color:white;
++}
++
++table td {
++ padding:.15em .5em;
++}
++
++table tr.even td {
++ background-color:#f5f5f5;
++}
++
++tr:nth-child(even) {
++ background-color: #eeeeee;
++
++}
++
++
++table th p:first-child, table td p:first-child, table li p:first-child,
++table th div.para:first-child, table td div.para:first-child, table li div.para:first-child {
++ margin-top:0px;
++ padding-top:0px;
++ display:inline;
++}
++
++th, td {
++ border-style:none;
++ vertical-align: top;
++/* border: 1px solid #000; */
++}
++
++.blockquote td,
++.simplelist th,
++.simplelist td {
++ border: none;
++}
++
++table table td {
++ border-bottom:1px dotted #aaa;
++ background-color:white;
++ padding:.6em 0px;
++}
++
++table table {
++ border:1px solid white;
++}
++
++td.remarkval {
++ color:#444;
++}
++
++td.fieldval {
++ font-weight:bold;
++}
++
++.lbname, .lbtype, .lbdescr, .lbdriver, .lbhost {
++ color:white;
++ font-weight:bold;
++ background-color:#999;
++ width:120px;
++}
++
++td.remarkval {
++ width:230px;
++}
++
++td.tname {
++ font-weight:bold;
++}
++
++th.dbfield {
++ width:120px;
++}
++
++th.dbtype {
++ width:70px;
++}
++
++th.dbdefault {
++ width:70px;
++}
++
++th.dbnul {
++ width:70px;
++}
++
++th.dbkey {
++ width:70px;
++}
++
++span.book {
++ margin-top:4em;
++ display:block;
++ font-size: 11pt;
++}
++
++span.book a{
++ font-weight:bold;
++}
++span.chapter {
++ display:block;
++}
++
++table.simplelist td, .calloutlist table td {
++ border-style: none;
++}
++
++
++table.lt-4-cols.lt-7-rows td {
++ border: none;
++}
++/*to simplify layout*/
++
++
++table.lt-4-cols.gt-14-rows tr:nth-child(odd) {
++ background-color: #fafafa;
++}
++/* to keep simple but stripe rows */
++
++
++.gt-8-cols td {
++ border-left: 1px solid #ccc;
++}
++
++.gt-8-cols td:first-child {
++ border-left: 0;
++}
++/* to apply vertical lines to differentiate columns*/
++
++/*Breadcrumbs*/
++#breadcrumbs ul li.first:before {
++ content:" ";
++}
++
++#breadcrumbs {
++ color:#900;
++ padding:3px;
++ margin-bottom:25px;
++}
++
++#breadcrumbs ul {
++ margin-left:0;
++ padding-left:0;
++ display:inline;
++ border:none;
++}
++
++#breadcrumbs ul li {
++ margin-left:0;
++ padding-left:2px;
++ border:none;
++ list-style:none;
++ display:inline;
++}
++
++#breadcrumbs ul li:before {
++ content:"\0020 \0020 \0020 \00BB \0020";
++ color:#333;
++}
++
++dl {
++ margin-top: 0px;
++ margin-left: 28px;
++}
++
++.toc dl {
++ margin-left: 10px;
++}
++
++/*index*/
++.glossary h3,
++.index h3 {
++ font-size: 20px;
++ color:#aaa;
++ margin:0px;
++}
++
++.indexdiv {
++ margin-bottom:1em;
++}
++
++.glossary dt,
++.index dt {
++ color:#444;
++ padding-top:.5em;
++}
++
++.glossary dl dl dt,
++.index dl dl dt {
++ color:#777;
++ font-weight:normal;
++ padding-top:0px;
++}
++
++.index dl dl dt:before {
++ content:"- ";
++ color:#ccc;
++}
++
++/*changes*/
++.footnote {
++ font-size: 10px;
++ margin: 0px;
++ color: #222;
++}
++
++.footnotes {
++ margin-bottom: 60px;
++}
++
++table .footnote {
++}
++
++sup {
++ margin:0px;
++ padding:0px;
++ font-size: 10px;
++ padding-left:0px;
++}
++
++.footnote {
++ position:relative;
++}
++
++.footnote sup {
++ color: black;
++ left: .4em;
++}
++
++.footnote a:link,
++.footnote a:visited {
++ text-decoration:none;
++ border: none;
++}
++
++.footnote .para sup {
++/* position:absolute; */
++ vertical-align:text-bottom;
++}
++
++a.footnote {
++ padding-right: 0.5em;
++ text-decoration:none;
++ border: none;
++}
++
++.footnote sup a:link,
++.footnote sup a:visited {
++ color:#92917d;
++ text-decoration:none;
++}
++
++.footnote:hover sup a {
++ text-decoration:none;
++}
++
++.footnote p,.footnote div.para {
++ padding-left:1em;
++}
++
++.footnote a:link,
++.footnote a:visited before{
++ color:#00537c;
++}
++
++.footnote a:hover {
++}
++
++/**/
++.pdf-break {
++ page-break-before: always;
++}
++
++div.legalnotice {
++ page-break-before: always;
++}
++
++div.abstract {
++ page-break-before: always;
++/* page-break-after: always;*/
++}
++
++div.chapter {
++ page-break-before: always;
++}
++
++
++div.titlepage, div.titlepage > div, div.titlepage > div > div {
++ page-break-inside: avoid;
++ page-break-after: avoid;
++}
++
++div.preface, div.part {
++ page-break-before: always;
++}
++
++div.appendix {
++ page-break-before: always;
++}
++
++div.section {
++ page-break-inside: auto;
++ page-break-before: auto;
++ page-break-after: auto;
++}
++
++
++dt.varlistentry {
++ page-break-inside: avoid;
++ page-break-after: avoid;
++}
++
++dd {
++ page-break-before: avoid;
++}
++
++div.note .replaceable,
++div.important .replaceable,
++div.warning .replaceable,
++div.note .keycap,
++div.important .keycap,
++div.warning .keycap
++{
++}
++
++ul li p:last-child, ul li para:last-child {
++ margin-bottom:0px;
++ padding-bottom:0px;
++}
++
++/*document navigation*/
++.docnav a, .docnav strong {
++ border:none;
++ text-decoration:none;
++ font-weight:normal;
++}
++
++.docnav {
++ list-style:none;
++ margin:0px;
++ padding:0px;
++ position:relative;
++ width:100%;
++ padding-bottom:2em;
++ padding-top:1em;
++ height:2.5em;
++ line-height:2.5em;
++/*
++ border-top:1px dotted #ccc;
++ background-color: rgba(240, 240, 240, 0.9);
++-webkitbox-shadow: 0px .15em .5em rgba(0,0,0,0.2);
++ -moz-box-shadow: 0px .15em .5em rgba(0,0,0,0.2);
++ box-shadow: 0px .15em .5em rgba(0,0,0,0.2);
++*/
++}
++
++.docnav li {
++ list-style:none;
++ margin:0px;
++ padding:0px;
++ display:inline;
++ font-size: 14px;
++}
++
++.docnav li:before {
++ content:" ";
++}
++
++.docnav li.previous, .docnav li.next {
++ position:absolute;
++ top:1.5em;
++}
++
++.docnav li.up, .docnav li.home {
++ margin:0px 1.5em;
++}
++
++.docnav.top li.home {
++ color: #336699;
++ font-size: 22pt;
++ font-weight: bold;
++}
++
++
++.docnav li.previous {
++ left:0px;
++ text-align:left;
++}
++
++.docnav li.next {
++ right:0px;
++ text-align:right;
++}
++
++.docnav li.previous strong, .docnav li.next strong {
++ height: 17px;
++ display: block;
++}
++
++.docnav {
++ margin:0 auto;
++ text-align:center;
++}
++
++.docnav li.next a strong {
++ background: url(../images/stock-go-forward.png) right 120% no-repeat;
++ padding-top:3px;
++ padding-bottom:4px;
++ padding-right:28px;
++}
++
++.docnav li.previous a strong {
++ background: url(../images/stock-go-back.png) left 120% no-repeat;
++ padding-top:3px;
++ padding-bottom:4px;
++ padding-left:28px;
++ padding-right:0.5em;
++}
++
++.docnav li.home a strong {
++ background: url(../images/stock-home.png) top left no-repeat;
++ padding:5px;
++ padding-left:28px;
++}
++
++.docnav li.up a strong {
++ background: url(../images/stock-go-up.png) top left no-repeat;
++ padding:5px;
++ padding-left:28px;
++}
++
++.docnav a:link, .docnav a:visited {
++ color:#666;
++}
++
++.docnav a:hover, .docnav a:focus, .docnav a:active {
++ color:black;
++}
++
++.docnav a {
++ max-width: 10px;
++ overflow:hidden;
++}
++
++.docnav a:link strong {
++ text-decoration:none;
++}
++
++.docnav {
++ margin:0 auto;
++ text-align:center;
++}
++
++ul.docnav {
++ margin-bottom: 1em;
++}
++/* Reports */
++.reports ul {
++ list-style:none;
++ margin:0px;
++ padding:0px;
++}
++
++.reports li{
++ margin:0px;
++ padding:0px;
++}
++
++.reports li.odd {
++ background-color: #eeeeee;
++ margin:0px;
++ padding:0px;
++}
++
++.reports dl {
++ display:inline;
++ margin:0px;
++ padding:0px;
++ float:right;
++ margin-right: 17em;
++ margin-top:-1.3em;
++}
++
++.reports dt {
++ display:inline;
++ margin:0px;
++ padding:0px;
++}
++
++.reports dd {
++ display:inline;
++ margin:0px;
++ padding:0px;
++ padding-right:.5em;
++}
++
++.reports h2, .reports h3{
++ display:inline;
++ padding-right:.5em;
++ font-size: 14px;
++ font-weight:normal;
++}
++
++.reports div.progress {
++ display:inline;
++ float:right;
++ width:16em;
++ background:#c00 url(../images/shine.png) top left repeat-x;
++ margin:0px;
++ margin-top:-1.3em;
++ padding:0px;
++ border:none;
++}
++
++/*uniform*/
++body.results, body.reports {
++ max-width:57em ;
++ padding:0px;
++}
++
++/*Progress Bar*/
++div.progress {
++ display:block;
++ float:left;
++ width:16em;
++ background:#c00 url(../images/shine.png) top left repeat-x;
++ height:1em;
++}
++
++div.progress span {
++ height:1em;
++ float:left;
++}
++
++div.progress span.translated {
++ background:#6c3 url(../images/shine.png) top left repeat-x;
++}
++
++div.progress span.fuzzy {
++ background:#ff9f00 url(../images/shine.png) top left repeat-x;
++}
++
++
++/*Results*/
++
++.results ul {
++ list-style:none;
++ margin:0px;
++ padding:0px;
++}
++
++.results li{
++ margin:0px;
++ padding:0px;
++}
++
++.results li.odd {
++ background-color: #eeeeee;
++ margin:0px;
++ padding:0px;
++}
++
++.results dl {
++ display:inline;
++ margin:0px;
++ padding:0px;
++ float:right;
++ margin-right: 17em;
++ margin-top:-1.3em;
++}
++
++.results dt {
++ display:inline;
++ margin:0px;
++ padding:0px;
++}
++
++.results dd {
++ display:inline;
++ margin:0px;
++ padding:0px;
++ padding-right:.5em;
++}
++
++.results h2, .results h3 {
++ display:inline;
++ padding-right:.5em;
++ font-size: 14px;
++ font-weight:normal;
++}
++
++.results div.progress {
++ display:inline;
++ float:right;
++ width:16em;
++ background:#c00 url(../images/shine.png) top left repeat-x;
++ margin:0px;
++ margin-top:-1.3em;
++ padding:0px;
++ border:none;
++}
++
++/* Dirty EVIL Mozilla hack for round corners */
++pre {
++ -moz-border-radius:11px;
++ -webkit-border-radius:11px;
++ border-radius: 11px;
++/* page-break-inside: avoid; */
++}
++
++.example {
++ -moz-border-radius:0px;
++ -webkit-border-radius:0px;
++ border-radius: 0px;
++ page-break-inside: avoid;
++}
++
++/* move these invisible fields out of the flow */
++.example > a:first-child,
++.table > a:first-child {
++ float: left;
++}
++
++.package, .citetitle {
++ font-style: italic;
++}
++
++.titlepage .edition,
++.titlepage .releaseinfo {
++ color: #336699;
++ background-color: transparent;
++ margin-top: 1em;
++ margin-bottom: 1em;
++ font-size: 20px;
++ font-weight: bold;
++ text-align: center;
++}
++
++span.remark {
++ background-color: #ff00ff;
++}
++
++.draft {
++ background-image: url(../images/watermark-draft.png);
++ background-repeat: repeat-y;
++ background-position: center;
++}
++
++.foreignphrase {
++ font-style: inherit;
++}
++
++dt {
++ clear:both;
++ page-break-inside: avoid;
++ page-break-after: avoid;
++}
++
++dt img {
++ border-style: none;
++ max-width: 112px;
++}
++
++dt object {
++ max-width: 112px;
++}
++
++dt .inlinemediaobject, dt object {
++ display: inline;
++ float: left;
++ margin-bottom: 1em;
++ padding-right: 1em;
++ width: 112px;
++}
++
++dl:after {
++ display: block;
++ clear: both;
++ content: "";
++}
++
++.toc dd {
++ padding-bottom: 0px;
++ margin-bottom: 1em;
++ padding-left: 1.3em;
++ margin-left: 0px;
++}
++
++div.toc > dl > dt {
++ padding-bottom: 0px;
++ margin-bottom: 0px;
++ margin-top: 1em;
++}
++
++
++.strikethrough {
++ text-decoration: line-through;
++}
++
++.underline {
++ text-decoration: underline;
++}
++
++.calloutlist img, .callout {
++ padding: 0px;
++ margin: 0px;
++ width: 12pt;
++ display: inline;
++ vertical-align: middle;
++}
++
++li.step > a:first-child {
++ display: block;
++}
++
++.stepalternatives {
++ list-style-image: none;
++ list-style-type: upper-alpha;
++}
++.task {
++/* page-break-inside: avoid; */
++}
++
++
++.added {
++ background-color: #99ff99;
++}
++
++.changed {
++ background-color: #ffff77;
++}
++
++.deleted {
++ background-color: #ff4455;
++ text-decoration: line-through;
++}
--- /dev/null
--- /dev/null
++@import url("common.css");
++@import url("overrides.css");
++@import url("lang.css");
--- /dev/null
--- /dev/null
++/*headings*/
++h1, h2, h3, h4, h5, h6,
++div.producttitle,
++div.subtitle,
++div.author div.author,
++div.translator div.translator,
++div.othercredit div.othercredit,
++div.editor div.editor,
++div.contrib div.contrib,
++.title,
++.titlepage .edition {
++}
++
++div.para {
++ margin-top: 1em;
++}
++/* inline syntax highlighting */
++.perl_Alert {
++ color: #0000ff;
++}
++
++.perl_BaseN {
++ color: #007f00;
++}
++
++.perl_BString {
++ color: #5C3566;
++}
++
++.perl_Char {
++ color: #ff00ff;
++}
++
++.perl_Comment {
++ color: #888888;
++}
++
++
++.perl_DataType {
++ color: #0000ff;
++}
++
++
++.perl_DecVal {
++ color: #00007f;
++}
++
++
++.perl_Error {
++ color: #ff0000;
++}
++
++
++.perl_Float {
++ color: #00007f;
++}
++
++
++.perl_Function {
++ color: #007f00;
++}
++
++
++.perl_IString {
++ color: #5C3566;
++}
++
++
++.perl_Keyword {
++ color: #002F5D;
++}
++
++
++.perl_Operator {
++ color: #ffa500;
++}
++
++
++.perl_Others {
++ color: #b03060;
++}
++
++
++.perl_RegionMarker {
++ color: #96b9ff;
++}
++
++
++.perl_Reserved {
++ color: #9b30ff;
++}
++
++
++.perl_String {
++ color: #5C3566;
++}
++
++
++.perl_Variable {
++ color: #0000ff;
++}
++
++
++.perl_Warning {
++ color: #0000ff;
++}
++
++b, strong {
++ font-weight: bolder;
++}
++
++code.command {
++ font-family: monospace;
++ font-weight: bolder;
++}
--- /dev/null
--- /dev/null
++@import url("common.css");
++@import url("overrides.css");
++@import url("lang.css");
++
++#tocframe {
++ display: none;
++}
++
++body.toc_embeded {
++ margin-left: 30px;
++}
++
++.producttitle {
++ color: #336699;
++}
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8" standalone="no"?>
++<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" width="32" height="32" id="svg3017">
++ <defs id="defs3019">
++ <linearGradient id="linearGradient2381">
++ <stop id="stop2383" style="stop-color:#ffffff;stop-opacity:1" offset="0"/>
++ <stop id="stop2385" style="stop-color:#ffffff;stop-opacity:0" offset="1"/>
++ </linearGradient>
++ <linearGradient x1="296.4996" y1="188.81061" x2="317.32471" y2="209.69398" id="linearGradient2371" xlink:href="#linearGradient2381" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.90776,0,0,0.90776,24.35648,49.24131)"/>
++ </defs>
++ <g transform="matrix(0.437808,-0.437808,0.437808,0.437808,-220.8237,43.55311)" id="g5089">
++ <path d="m 8.4382985,-6.28125 c -0.6073916,0 -4.3132985,5.94886271 -4.3132985,8.25 l 0,26.71875 c 0,0.846384 0.5818159,1.125 1.15625,1.125 l 25.5625,0 c 0.632342,0 1.125001,-0.492658 1.125,-1.125 l 0,-5.21875 0.28125,0 c 0.49684,0 0.906249,-0.409411 0.90625,-0.90625 l 0,-27.9375 c 0,-0.4968398 -0.40941,-0.90625 -0.90625,-0.90625 l -23.8117015,0 z" transform="translate(282.8327,227.1903)" id="path5091" style="fill:#5c5c4f;stroke:#000000;stroke-width:3.23021388;stroke-miterlimit:4;stroke-dasharray:none"/>
++ <rect width="27.85074" height="29.369793" rx="1.1414107" ry="1.1414107" x="286.96509" y="227.63805" id="rect5093" style="fill:#032c87"/>
++ <path d="m 288.43262,225.43675 25.2418,0 0,29.3698 -26.37615,0.0241 1.13435,-29.39394 z" id="rect5095" style="fill:#ffffff"/>
++ <path d="m 302.44536,251.73726 c 1.38691,7.85917 -0.69311,11.28365 -0.69311,11.28365 2.24384,-1.60762 3.96426,-3.47694 4.90522,-5.736 0.96708,2.19264 1.83294,4.42866 4.27443,5.98941 0,0 -1.59504,-7.2004 -1.71143,-11.53706 l -6.77511,0 z" id="path5097" style="fill:#a70000;fill-opacity:1;stroke-width:2"/>
++ <rect width="25.241802" height="29.736675" rx="0.89682275" ry="0.89682275" x="290.73544" y="220.92249" id="rect5099" style="fill:#809cc9"/>
++ <path d="m 576.47347,725.93939 6.37084,0.41502 0.4069,29.51809 c -1.89202,-1.31785 -6.85427,-3.7608 -8.26232,-1.68101 l 0,-26.76752 c 0,-0.82246 0.66212,-1.48458 1.48458,-1.48458 z" transform="matrix(0.499065,-0.866565,0,1,0,0)" id="rect5101" style="fill:#4573b3;fill-opacity:1"/>
++ <path d="m 293.2599,221.89363 20.73918,0 c 0.45101,0 0.8141,0.3631 0.8141,0.81411 0.21547,6.32836 -19.36824,21.7635 -22.36739,17.59717 l 0,-17.59717 c 0,-0.45101 0.3631,-0.81411 0.81411,-0.81411 z" id="path5103" style="opacity:0.65536726;fill:url(#linearGradient2371);fill-opacity:1"/>
++ </g>
++</svg>
--- /dev/null
--- /dev/null
++ProtocolSpec_xml = custom_target(
++ 'ProtocolSpec.xml',
++ command: [ xsltproc, '-o', '@OUTPUT@', files('../protocol-to-docbook.xsl'), '@INPUT@' ],
++ input: wayland_protocol_xml,
++ output: 'ProtocolSpec.xml'
++)
++
++ProtocolInterfaces_xml = custom_target(
++ 'ProtocolInterfaces.xml',
++ command: [ xsltproc, '-o', '@OUTPUT@', files('../protocol-interfaces-to-docbook.xsl'), '@INPUT@' ],
++ input: wayland_protocol_xml,
++ output: 'ProtocolInterfaces.xml'
++)
++
++ClientAPI_combined = custom_target(
++ 'ClientAPI-combined',
++ command: [ xsltproc, '-o', '@OUTPUT@', '@INPUT@' ],
++ input: [ doxygen_Client_combine_xslt, doxygen_Client_index_xml ],
++ output: 'ClientAPI-combined.xml'
++)
++
++to_publican_xsl = files('../doxygen-to-publican.xsl')
++
++ClientAPI_xml = custom_target(
++ 'ClientAPI.xml',
++ command: [ xsltproc, '-o', '@OUTPUT@', '--stringparam', 'which', 'Client', to_publican_xsl, '@INPUT@' ],
++ input: ClientAPI_combined,
++ output: 'ClientAPI.xml'
++)
++
++ServerAPI_combined = custom_target(
++ 'ServerAPI-combined',
++ command: [ xsltproc, '-o', '@OUTPUT@', '@INPUT@' ],
++ input: [ doxygen_Server_combine_xslt, doxygen_Server_index_xml ],
++ output: 'ServerAPI-combined.xml'
++)
++
++ServerAPI_xml = custom_target(
++ 'ServerAPI.xml',
++ command: [ xsltproc, '-o', '@OUTPUT@', '--stringparam', 'which', 'Server', to_publican_xsl, '@INPUT@' ],
++ input: ServerAPI_combined,
++ output: 'ServerAPI.xml'
++)
++
++
++publican_sources = [
++ 'Wayland.ent',
++ # 'Wayland.xml', # handled specially
++ 'Book_Info.xml',
++ 'Author_Group.xml',
++ 'Foreword.xml',
++ 'Preface.xml',
++ 'Revision_History.xml',
++ 'Protocol.xml',
++ 'Xwayland.xml',
++ 'Compositors.xml',
++ 'Client.xml',
++ 'Server.xml'
++]
++
++publican_processed_main = configure_file(
++ input: 'Wayland.xml',
++ output: 'Wayland.xml',
++ copy: true
++)
++
++publican_copied_sources = []
++foreach src: publican_sources
++ publican_copied_sources += configure_file(
++ input: src,
++ output: src,
++ copy: true
++ )
++endforeach
++
++publican_processed_sources = [
++ 'Architecture.xml',
++ 'Introduction.xml'
++]
++
++publican_processed_targets = []
++foreach src: publican_processed_sources
++ publican_processed_targets += custom_target(
++ src,
++ command: [ xsltproc, '-o', '@OUTPUT@', '--stringparam', 'basedir', '.', merge_mapcoords_xsl, '@INPUT@' ],
++ input: src,
++ output: src
++ )
++endforeach
++
++publican_css_sources = files([
++ 'css/brand.css',
++ 'css/common.css',
++ 'css/default.css',
++ 'css/epub.css',
++ 'css/print.css'
++])
++
++install_data(
++ publican_css_sources,
++ install_dir: join_paths(publican_install_prefix, publican_html_dir, 'css')
++)
++
++publican_img_sources = files([
++ 'images/icon.svg',
++ 'images/wayland.png',
++ 'images/xwayland-architecture.png'
++])
++
++install_data(
++ publican_img_sources,
++ install_dir: join_paths(publican_install_prefix, publican_html_dir, 'images')
++)
--- /dev/null
--- /dev/null
++wayland_egl = library(
++ 'wayland-egl',
++ sources: [
++ 'wayland-egl.c',
++ wayland_client_protocol_h
++ ],
++ include_directories: src_inc,
++ version: meson.project_version(),
++ install: true
++)
++
++executable('wayland-egl-abi-check', 'wayland-egl-abi-check.c')
++
++nm_path = find_program('nm').full_path()
++
++test(
++ 'wayland-egl symbols check',
++ find_program('wayland-egl-symbols-check'),
++ env: [
++ 'WAYLAND_EGL_LIB=@0@'.format(wayland_egl.full_path()),
++ 'NM=@0@'.format(nm_path)
++ ]
++)
++
++install_headers([
++ 'wayland-egl.h',
++ 'wayland-egl-core.h',
++ 'wayland-egl-backend.h'
++])
++
++pkgconfig.generate(
++ name: 'wayland-egl',
++ description: 'Frontend wayland-egl library',
++ version: '18.1.0',
++ requires: 'wayland-client',
++ libraries: wayland_egl
++)
++
++pkgconfig.generate(
++ name: 'wayland-egl-backend',
++ description: 'Backend wayland-egl interface',
++ version: '3'
++)
++
++wayland_egl_dep = declare_dependency(
++ link_with: wayland_egl,
++ include_directories: [ root_inc, include_directories('.') ],
++)
++
++if meson.version().version_compare('>= 0.54.0')
++ meson.override_dependency('wayland-egl', wayland_egl_dep)
++endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#include <stddef.h> /* offsetof */
++#include <stdio.h> /* printf */
++
++#include "wayland-egl-backend.h" /* Current struct wl_egl_window implementation */
++
++/*
++ * Following are previous implementations of wl_egl_window.
++ *
++ * DO NOT EVER CHANGE!
++ */
++
++/* From: 214fc6e850 - Benjamin Franzke : egl: Implement libwayland-egl */
++struct wl_egl_window_v0 {
++ struct wl_surface *surface;
++
++ int width;
++ int height;
++ int dx;
++ int dy;
++
++ int attached_width;
++ int attached_height;
++};
++
++/* From: ca3ed3e024 - Ander Conselvan de Oliveira : egl/wayland: Don't invalidate drawable on swap buffers */
++struct wl_egl_window_v1 {
++ struct wl_surface *surface;
++
++ int width;
++ int height;
++ int dx;
++ int dy;
++
++ int attached_width;
++ int attached_height;
++
++ void *private;
++ void (*resize_callback)(struct wl_egl_window *, void *);
++};
++
++/* From: 690ead4a13 - Stencel, Joanna : egl/wayland-egl: Fix for segfault in dri2_wl_destroy_surface. */
++#define WL_EGL_WINDOW_VERSION_v2 2
++struct wl_egl_window_v2 {
++ struct wl_surface *surface;
++
++ int width;
++ int height;
++ int dx;
++ int dy;
++
++ int attached_width;
++ int attached_height;
++
++ void *private;
++ void (*resize_callback)(struct wl_egl_window *, void *);
++ void (*destroy_window_callback)(void *);
++};
++
++/* From: 2d5d61bc49 - Miguel A. Vico : wayland-egl: Make wl_egl_window a versioned struct */
++#define WL_EGL_WINDOW_VERSION_v3 3
++struct wl_egl_window_v3 {
++ const intptr_t version;
++
++ int width;
++ int height;
++ int dx;
++ int dy;
++
++ int attached_width;
++ int attached_height;
++
++ void *driver_private;
++ void (*resize_callback)(struct wl_egl_window *, void *);
++ void (*destroy_window_callback)(void *);
++
++ struct wl_surface *surface;
++};
++
++
++/* This program checks we keep a backwards-compatible struct wl_egl_window
++ * definition whenever it is modified in wayland-egl-backend.h.
++ *
++ * The previous definition should be added above as a new struct
++ * wl_egl_window_vN, and the appropriate checks should be added below
++ */
++
++#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
++
++#define CHECK_RENAMED_MEMBER(a_ver, b_ver, a_member, b_member) \
++ do { \
++ if (offsetof(struct wl_egl_window ## a_ver, a_member) != \
++ offsetof(struct wl_egl_window ## b_ver, b_member)) { \
++ printf("Backwards incompatible change detected!\n " \
++ "offsetof(struct wl_egl_window" #a_ver "::" #a_member ") != " \
++ "offsetof(struct wl_egl_window" #b_ver "::" #b_member ")\n"); \
++ return 1; \
++ } \
++ \
++ if (MEMBER_SIZE(struct wl_egl_window ## a_ver, a_member) != \
++ MEMBER_SIZE(struct wl_egl_window ## b_ver, b_member)) { \
++ printf("Backwards incompatible change detected!\n " \
++ "MEMBER_SIZE(struct wl_egl_window" #a_ver "::" #a_member ") != " \
++ "MEMBER_SIZE(struct wl_egl_window" #b_ver "::" #b_member ")\n"); \
++ return 1; \
++ } \
++ } while (0)
++
++#define CHECK_MEMBER(a_ver, b_ver, member) CHECK_RENAMED_MEMBER(a_ver, b_ver, member, member)
++#define CHECK_MEMBER_CURRENT(a_ver, member) CHECK_MEMBER(a_ver,, member)
++
++#define CHECK_SIZE(a_ver, b_ver) \
++ do { \
++ if (sizeof(struct wl_egl_window ## a_ver) > \
++ sizeof(struct wl_egl_window ## b_ver)) { \
++ printf("Backwards incompatible change detected!\n " \
++ "sizeof(struct wl_egl_window" #a_ver ") > " \
++ "sizeof(struct wl_egl_window" #b_ver ")\n"); \
++ return 1; \
++ } \
++ } while (0)
++
++#define CHECK_SIZE_CURRENT(a_ver) \
++ do { \
++ if (sizeof(struct wl_egl_window ## a_ver) != \
++ sizeof(struct wl_egl_window)) { \
++ printf("Backwards incompatible change detected!\n " \
++ "sizeof(struct wl_egl_window" #a_ver ") != " \
++ "sizeof(struct wl_egl_window)\n"); \
++ return 1; \
++ } \
++ } while (0)
++
++#define CHECK_VERSION(a_ver, b_ver) \
++ do { \
++ if ((WL_EGL_WINDOW_VERSION ## a_ver) >= \
++ (WL_EGL_WINDOW_VERSION ## b_ver)) { \
++ printf("Backwards incompatible change detected!\n " \
++ "WL_EGL_WINDOW_VERSION" #a_ver " >= " \
++ "WL_EGL_WINDOW_VERSION" #b_ver "\n"); \
++ return 1; \
++ } \
++ } while (0)
++
++#define CHECK_VERSION_CURRENT(a_ver) \
++ do { \
++ if ((WL_EGL_WINDOW_VERSION ## a_ver) != \
++ (WL_EGL_WINDOW_VERSION)) { \
++ printf("Backwards incompatible change detected!\n " \
++ "WL_EGL_WINDOW_VERSION" #a_ver " != " \
++ "WL_EGL_WINDOW_VERSION\n"); \
++ return 1; \
++ } \
++ } while (0)
++
++int main(int argc, char **argv)
++{
++ /* Check wl_egl_window_v1 ABI against wl_egl_window_v0 */
++ CHECK_MEMBER(_v0, _v1, surface);
++ CHECK_MEMBER(_v0, _v1, width);
++ CHECK_MEMBER(_v0, _v1, height);
++ CHECK_MEMBER(_v0, _v1, dx);
++ CHECK_MEMBER(_v0, _v1, dy);
++ CHECK_MEMBER(_v0, _v1, attached_width);
++ CHECK_MEMBER(_v0, _v1, attached_height);
++
++ CHECK_SIZE(_v0, _v1);
++
++ /* Check wl_egl_window_v2 ABI against wl_egl_window_v1 */
++ CHECK_MEMBER(_v1, _v2, surface);
++ CHECK_MEMBER(_v1, _v2, width);
++ CHECK_MEMBER(_v1, _v2, height);
++ CHECK_MEMBER(_v1, _v2, dx);
++ CHECK_MEMBER(_v1, _v2, dy);
++ CHECK_MEMBER(_v1, _v2, attached_width);
++ CHECK_MEMBER(_v1, _v2, attached_height);
++ CHECK_MEMBER(_v1, _v2, private);
++ CHECK_MEMBER(_v1, _v2, resize_callback);
++
++ CHECK_SIZE(_v1, _v2);
++
++ /* Check wl_egl_window_v3 ABI against wl_egl_window_v2 */
++ CHECK_RENAMED_MEMBER(_v2, _v3, surface, version);
++ CHECK_MEMBER (_v2, _v3, width);
++ CHECK_MEMBER (_v2, _v3, height);
++ CHECK_MEMBER (_v2, _v3, dx);
++ CHECK_MEMBER (_v2, _v3, dy);
++ CHECK_MEMBER (_v2, _v3, attached_width);
++ CHECK_MEMBER (_v2, _v3, attached_height);
++ CHECK_RENAMED_MEMBER(_v2, _v3, private, driver_private);
++ CHECK_MEMBER (_v2, _v3, resize_callback);
++ CHECK_MEMBER (_v2, _v3, destroy_window_callback);
++
++ CHECK_SIZE (_v2, _v3);
++ CHECK_VERSION(_v2, _v3);
++
++ /* Check current wl_egl_window ABI against wl_egl_window_v3 */
++ CHECK_MEMBER_CURRENT(_v3, version);
++ CHECK_MEMBER_CURRENT(_v3, width);
++ CHECK_MEMBER_CURRENT(_v3, height);
++ CHECK_MEMBER_CURRENT(_v3, dx);
++ CHECK_MEMBER_CURRENT(_v3, dy);
++ CHECK_MEMBER_CURRENT(_v3, attached_width);
++ CHECK_MEMBER_CURRENT(_v3, attached_height);
++ CHECK_MEMBER_CURRENT(_v3, driver_private);
++ CHECK_MEMBER_CURRENT(_v3, resize_callback);
++ CHECK_MEMBER_CURRENT(_v3, destroy_window_callback);
++ CHECK_MEMBER_CURRENT(_v3, surface);
++
++ CHECK_SIZE_CURRENT (_v3);
++ CHECK_VERSION_CURRENT(_v3);
++
++ return 0;
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2011 Benjamin Franzke
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Authors:
++ * Benjamin Franzke <benjaminfranzke@googlemail.com>
++ */
++
++#ifndef _WAYLAND_EGL_PRIV_H
++#define _WAYLAND_EGL_PRIV_H
++
++#include <stdint.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*
++ * NOTE: This version must be kept in sync with the version field in the
++ * wayland-egl-backend pkgconfig file generated in meson.build.
++ */
++#define WL_EGL_WINDOW_VERSION 3
++
++struct wl_surface;
++
++struct wl_egl_window {
++ const intptr_t version;
++
++ int width;
++ int height;
++ int dx;
++ int dy;
++
++ int attached_width;
++ int attached_height;
++
++ void *driver_private;
++ void (*resize_callback)(struct wl_egl_window *, void *);
++ void (*destroy_window_callback)(void *);
++
++ struct wl_surface *surface;
++};
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2011 Kristian Høgsberg
++ * Copyright © 2011 Benjamin Franzke
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_EGL_CORE_H
++#define WAYLAND_EGL_CORE_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define WL_EGL_PLATFORM 1
++
++struct wl_egl_window;
++struct wl_surface;
++
++struct wl_egl_window *
++wl_egl_window_create(struct wl_surface *surface,
++ int width, int height);
++
++void
++wl_egl_window_destroy(struct wl_egl_window *egl_window);
++
++void
++wl_egl_window_resize(struct wl_egl_window *egl_window,
++ int width, int height,
++ int dx, int dy);
++
++void
++wl_egl_window_get_attached_size(struct wl_egl_window *egl_window,
++ int *width, int *height);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
--- /dev/null
--- /dev/null
++#!/bin/sh
++set -eu
++
++RET=0
++LIB=${WAYLAND_EGL_LIB}
++
++if ! test -f "$LIB"; then
++ echo "Test binary \"$LIB\" does not exist"
++ exit 99
++fi
++
++if ! test -n "$NM"; then
++ echo "nm environment variable not set"
++ exit 99
++fi
++
++AVAIL_FUNCS="$($NM -D --format=bsd --defined-only $LIB | awk '{print $3}')"
++
++# Official ABI, taken from the header.
++REQ_FUNCS="wl_egl_window_resize
++wl_egl_window_create
++wl_egl_window_destroy
++wl_egl_window_get_attached_size
++"
++
++NEW_ABI=$(echo "$AVAIL_FUNCS" | while read func; do
++ echo "$func" | grep -q "^_" && continue
++ echo "$REQ_FUNCS" | grep -q "^$func$" && continue
++
++ echo $func
++done)
++
++if test -n "$NEW_ABI"; then
++ echo "New ABI detected - If intentional, update the test."
++ echo "$NEW_ABI"
++ RET=1
++fi
++
++REMOVED_ABI=$(echo "$REQ_FUNCS" | while read func; do
++ echo "$AVAIL_FUNCS" | grep -q "^$func$" && continue
++
++ echo $func
++done)
++
++if test -n "$REMOVED_ABI"; then
++ echo "ABI break detected - Required symbol(s) no longer exported!"
++ echo "$REMOVED_ABI"
++ RET=1
++fi
++
++exit $RET
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2011 Kristian Høgsberg
++ * Copyright © 2011 Benjamin Franzke
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Authors:
++ * Kristian Høgsberg <krh@bitplanet.net>
++ * Benjamin Franzke <benjaminfranzke@googlemail.com>
++ */
++
++#include <stdlib.h>
++#include <string.h>
++
++#include "wayland-egl.h"
++#include "wayland-egl-backend.h"
++#include "wayland-util.h"
++
++
++/** Resize the EGL window
++ *
++ * \param egl_window A pointer to a struct wl_egl_window
++ * \param width The new width
++ * \param height The new height
++ * \param dx Offset on the X axis
++ * \param dy Offset on the Y axis
++ *
++ * Note that applications should prefer using the wl_surface.offset request if
++ * the associated wl_surface has the interface version 5 or higher.
++ *
++ * If the wl_surface.offset request is used, applications MUST pass 0 to both
++ * dx and dy.
++ */
++WL_EXPORT void
++wl_egl_window_resize(struct wl_egl_window *egl_window,
++ int width, int height,
++ int dx, int dy)
++{
++ if (width <= 0 || height <= 0)
++ return;
++
++ egl_window->width = width;
++ egl_window->height = height;
++ egl_window->dx = dx;
++ egl_window->dy = dy;
++
++ if (egl_window->resize_callback)
++ egl_window->resize_callback(egl_window, egl_window->driver_private);
++}
++
++WL_EXPORT struct wl_egl_window *
++wl_egl_window_create(struct wl_surface *surface,
++ int width, int height)
++{
++ struct wl_egl_window *egl_window;
++
++ if (width <= 0 || height <= 0)
++ return NULL;
++
++ egl_window = calloc(1, sizeof *egl_window);
++ if (!egl_window)
++ return NULL;
++
++ /* Cast away the constness to set the version number.
++ *
++ * We want the const notation since it gives an explicit
++ * feedback to the backend implementation, should it try to
++ * change it.
++ *
++ * The latter in itself is not too surprising as these days APIs
++ * tend to provide bidirectional version field.
++ */
++ intptr_t *version = (intptr_t *)&egl_window->version;
++ *version = WL_EGL_WINDOW_VERSION;
++
++ egl_window->surface = surface;
++
++ egl_window->width = width;
++ egl_window->height = height;
++
++ return egl_window;
++}
++
++WL_EXPORT void
++wl_egl_window_destroy(struct wl_egl_window *egl_window)
++{
++ if (egl_window->destroy_window_callback)
++ egl_window->destroy_window_callback(egl_window->driver_private);
++ free(egl_window);
++}
++
++WL_EXPORT void
++wl_egl_window_get_attached_size(struct wl_egl_window *egl_window,
++ int *width, int *height)
++{
++ if (width)
++ *width = egl_window->attached_width;
++ if (height)
++ *height = egl_window->attached_height;
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2011 Kristian Høgsberg
++ * Copyright © 2011 Benjamin Franzke
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_EGL_H
++#define WAYLAND_EGL_H
++
++#include <wayland-client.h>
++#include "wayland-egl-core.h"
++
++#endif
--- /dev/null
--- /dev/null
++project(
++ 'wayland', 'c',
++ version: '1.21.90',
++ license: 'MIT',
++ meson_version: '>= 0.56.0',
++ default_options: [
++ 'warning_level=2',
++ 'buildtype=debugoptimized',
++ 'c_std=c99',
++ ]
++)
++wayland_version = meson.project_version().split('.')
++
++config_h = configuration_data()
++config_h.set_quoted('PACKAGE', meson.project_name())
++config_h.set_quoted('PACKAGE_VERSION', meson.project_version())
++
++cc_args = []
++if host_machine.system() != 'freebsd'
++ cc_args += ['-D_POSIX_C_SOURCE=200809L']
++endif
++add_project_arguments(cc_args, language: 'c')
++
++compiler_flags = [
++ '-Wno-unused-parameter',
++ '-Wstrict-prototypes',
++ '-Wmissing-prototypes',
++ '-fvisibility=hidden',
++]
++
++cc = meson.get_compiler('c')
++add_project_arguments(
++ cc.get_supported_arguments(compiler_flags),
++ language: 'c'
++)
++
++foreach h: [ 'sys/prctl.h', 'sys/procctl.h', 'sys/ucred.h' ]
++ config_h.set('HAVE_' + h.underscorify().to_upper(), cc.has_header(h))
++endforeach
++
++have_funcs = [
++ 'accept4',
++ 'mkostemp',
++ 'posix_fallocate',
++ 'prctl',
++ 'memfd_create',
++ 'mremap',
++ 'strndup',
++]
++foreach f: have_funcs
++ config_h.set('HAVE_' + f.underscorify().to_upper(), cc.has_function(f))
++endforeach
++config_h.set10('HAVE_XUCRED_CR_PID', cc.has_member('struct xucred', 'cr_pid', prefix : '#include <sys/ucred.h>'))
++have_broken_msg_cmsg_cloexec = false
++if host_machine.system() == 'freebsd'
++ have_broken_msg_cmsg_cloexec = not cc.compiles('''
++#include <sys/param.h> /* To get __FreeBSD_version. */
++#if __FreeBSD_version < 1300502 || \
++ (__FreeBSD_version >= 1400000 && __FreeBSD_version < 1400006)
++/*
++ * FreeBSD had a broken implementation of MSG_CMSG_CLOEXEC between 2015 and
++ * 2021. Check if we are compiling against a version that includes the fix
++ * (https://cgit.freebsd.org/src/commit/?id=6ceacebdf52211).
++ */
++#error "Broken MSG_CMSG_CLOEXEC"
++#endif
++''', name : 'MSG_CMSG_CLOEXEC works correctly')
++endif
++config_h.set10('HAVE_BROKEN_MSG_CMSG_CLOEXEC', have_broken_msg_cmsg_cloexec)
++
++if get_option('libraries')
++ if host_machine.system() == 'freebsd'
++ # When building for FreeBSD, epoll(7) is provided by a userspace
++ # wrapper around kqueue(2).
++ epoll_dep = dependency('epoll-shim')
++ else
++ # Otherwise, assume that epoll(7) is supported natively.
++ epoll_dep = []
++ endif
++ ffi_dep = dependency('libffi')
++
++ decls = [
++ { 'header': 'sys/signalfd.h', 'symbol': 'SFD_CLOEXEC' },
++ { 'header': 'sys/timerfd.h', 'symbol': 'TFD_CLOEXEC' },
++ { 'header': 'time.h', 'symbol': 'CLOCK_MONOTONIC' },
++ ]
++
++ foreach d: decls
++ if not cc.has_header_symbol(d['header'], d['symbol'], dependencies: epoll_dep, args: cc_args)
++ error('@0@ is needed to compile Wayland libraries'.format(d['symbol']))
++ endif
++ endforeach
++
++ rt_dep = []
++ if not cc.has_function('clock_gettime', prefix: '#include <time.h>')
++ rt_dep = cc.find_library('rt')
++ if not cc.has_function('clock_gettime', prefix: '#include <time.h>', dependencies: rt_dep, args: cc_args)
++ error('clock_gettime not found')
++ endif
++ endif
++endif
++
++configure_file(
++ output: 'config.h',
++ configuration: config_h,
++)
++
++pkgconfig = import('pkgconfig')
++
++wayland_protocol_xml = files('protocol/wayland.xml')
++
++root_inc = include_directories('.')
++protocol_inc = include_directories('protocol')
++src_inc = include_directories('src')
++
++subdir('src')
++
++if get_option('libraries')
++ subdir('cursor')
++ subdir('egl')
++endif
++if get_option('tests')
++ subdir('tests')
++endif
++if get_option('documentation')
++ subdir('doc')
++endif
++
++if get_option('scanner')
++ install_data([
++ 'wayland-scanner.mk',
++ 'protocol/wayland.xml',
++ 'protocol/wayland.dtd',
++ ])
++
++ install_data(
++ [ 'wayland-scanner.m4' ],
++ install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'aclocal'),
++ )
++endif
--- /dev/null
--- /dev/null
++option('libraries',
++ description: 'Compile Wayland libraries',
++ type: 'boolean',
++ value: true)
++option('scanner',
++ description: 'Compile wayland-scanner binary',
++ type: 'boolean',
++ value: true)
++option('tests',
++ description: 'Compile Wayland tests',
++ type: 'boolean',
++ value: true)
++option('documentation',
++ description: 'Build the documentation (requires Doxygen, dot, xmlto, xsltproc)',
++ type: 'boolean',
++ value: true)
++option('dtd_validation',
++ description: 'Validate the protocol DTD (requires libxml2)',
++ type: 'boolean',
++ value: true)
++option('icon_directory',
++ description: 'Location used to look for cursors (defaults to ${datadir}/icons if unset)',
++ type: 'string',
++ value: '')
--- /dev/null
--- /dev/null
++wayland.html
++.wayland.xml.valid
--- /dev/null
--- /dev/null
++#!/usr/bin/env python3
++
++# This script synchronizes wayland.xml's wl_shm.format enum with drm_fourcc.h.
++# Invoke it to update wayland.xml, then manually check the changes applied.
++#
++# Requires Python 3, python-lxml, a C compiler and pkg-config.
++
++import os
++import subprocess
++import sys
++import tempfile
++# We need lxml instead of the standard library because we want
++# Element.sourceline
++from lxml import etree as ElementTree
++
++proto_dir = os.path.dirname(os.path.realpath(__file__))
++wayland_proto = proto_dir + "/wayland.xml"
++
++cc = os.getenv("CC", "cc")
++pkg_config = os.getenv("PKG_CONFIG", "pkg-config")
++
++# Find drm_fourcc.h
++version = subprocess.check_output([pkg_config, "libdrm",
++ "--modversion"]).decode().strip()
++cflags = subprocess.check_output([pkg_config, "libdrm",
++ "--cflags-only-I"]).decode().strip().split()
++libdrm_include = None
++for include_flag in cflags:
++ if not include_flag.startswith("-I"):
++ raise Exception("Expected one include dir for libdrm")
++ include_dir = include_flag[2:]
++ if include_dir.endswith("/libdrm"):
++ libdrm_include = include_dir
++ fourcc_include = libdrm_include + "/drm_fourcc.h"
++if libdrm_include == None:
++ raise Exception("Failed to find libdrm include dir")
++
++print("Using libdrm " + version, file=sys.stderr)
++
++def drm_format_to_wl(ident):
++ return ident.replace("DRM_FORMAT_", "").lower()
++
++# Collect DRM format constant names
++ident_list = []
++descriptions = {}
++prev_comment = None
++with open(fourcc_include) as input_file:
++ for l in input_file.readlines():
++ l = l.strip()
++
++ # Collect comments right before format definitions
++ if l.startswith("/*") and l.endswith("*/"):
++ prev_comment = l[2:-2]
++ continue
++ desc = prev_comment
++ prev_comment = None
++
++ # Recognize format definitions
++ parts = l.split()
++ if len(parts) < 3 or parts[0] != "#define":
++ continue
++ ident = parts[1]
++ if not ident.startswith("DRM_FORMAT_") or ident.startswith(
++ "DRM_FORMAT_MOD_"):
++ continue
++
++ ident_list.append(ident)
++
++ # Prefer in-line comments
++ if l.endswith("*/"):
++ desc = l[l.rfind("/*") + 2:-2]
++ if desc != None:
++ descriptions[drm_format_to_wl(ident)] = desc.strip()
++
++# Collect DRM format values
++idents = {}
++with tempfile.TemporaryDirectory() as work_dir:
++ c_file_name = work_dir + "/print-formats.c"
++ exe_file_name = work_dir + "/print-formats"
++
++ with open(c_file_name, "w+") as c_file:
++ c_file.write('#include <inttypes.h>\n')
++ c_file.write('#include <stdint.h>\n')
++ c_file.write('#include <stdio.h>\n')
++ c_file.write('#include <drm_fourcc.h>\n')
++ c_file.write('\n')
++ c_file.write('int main(void) {\n')
++ for ident in ident_list:
++ c_file.write('printf("0x%" PRIX64 "\\n", (uint64_t)' + ident + ');\n')
++ c_file.write('}\n')
++
++ subprocess.check_call([cc, "-Wall", "-Wextra", "-o", exe_file_name,
++ c_file_name] + cflags)
++ output = subprocess.check_output([exe_file_name]).decode().strip()
++ for i, val in enumerate(output.splitlines()):
++ idents[ident_list[i]] = val
++
++# We don't need those
++del idents["DRM_FORMAT_BIG_ENDIAN"]
++del idents["DRM_FORMAT_INVALID"]
++del idents["DRM_FORMAT_RESERVED"]
++
++# Convert from DRM constants to Wayland wl_shm.format entries
++formats = {}
++for ident, val in idents.items():
++ formats[drm_format_to_wl(ident)] = val.lower()
++# Special case for ARGB8888 and XRGB8888
++formats["argb8888"] = "0"
++formats["xrgb8888"] = "1"
++
++print("Loaded {} formats from drm_fourcc.h".format(len(formats)), file=sys.stderr)
++
++tree = ElementTree.parse("wayland.xml")
++root = tree.getroot()
++wl_shm_format = root.find("./interface[@name='wl_shm']/enum[@name='format']")
++if wl_shm_format == None:
++ raise Exception("wl_shm.format not found in wayland.xml")
++
++# Remove formats we already know about
++last_line = None
++for node in wl_shm_format:
++ if node.tag != "entry":
++ continue
++ fmt = node.attrib["name"]
++ val = node.attrib["value"]
++ if fmt not in formats:
++ raise Exception("Format present in wl_shm.formats but not in "
++ "drm_fourcc.h: " + fmt)
++ if val != formats[fmt]:
++ raise Exception("Format value in wl_shm.formats ({}) differs "
++ "from value in drm_fourcc.h ({}) for format {}"
++ .format(val, formats[fmt], fmt))
++ del formats[fmt]
++ last_line = node.sourceline
++if last_line == None:
++ raise Exception("Expected at least one existing wl_shm.format entry")
++
++print("Adding {} formats to wayland.xml...".format(len(formats)), file=sys.stderr)
++
++# Append new formats
++new_wayland_proto = wayland_proto + ".new"
++with open(new_wayland_proto, "w+") as output_file, \
++ open(wayland_proto) as input_file:
++ for i, l in enumerate(input_file.readlines()):
++ output_file.write(l)
++ if i + 1 == last_line:
++ for fmt, val in formats.items():
++ output_file.write(' <entry name="{}" value="{}"'
++ .format(fmt, val))
++ if fmt in descriptions:
++ output_file.write(' summary="{}"'.format(descriptions[fmt]))
++ output_file.write('/>\n')
++os.rename(new_wayland_proto, wayland_proto)
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="build_time_wayland_tests">
++
++ <copyright>
++ Copyright © 2017 Samsung Electronics Co., Ltd
++
++ Permission is hereby granted, free of charge, to any person
++ obtaining a copy of this software and associated documentation files
++ (the "Software"), to deal in the Software without restriction,
++ including without limitation the rights to use, copy, modify, merge,
++ publish, distribute, sublicense, and/or sell copies of the Software,
++ and to permit persons to whom the Software is furnished to do so,
++ subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the
++ next paragraph) shall be included in all copies or substantial
++ portions of the Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ SOFTWARE.
++ </copyright>
++
++ <interface name="fd_passer" version="2">
++ <description summary="Sends an event with an fd">
++ A trivial interface for fd passing tests.
++ </description>
++
++ <request name="destroy" type="destructor"/>
++
++ <event name="pre_fd"/>
++
++ <event name="fd">
++ <description summary="passes a file descriptor"/>
++ <arg name="fd" type="fd" summary="file descriptor"/>
++ </event>
++
++ <!-- Version 2 additions -->
++ <request name="conjoin" since="2">
++ <description summary="register another fd passer with this one">
++ Tells this fd passer object about another one to send events
++ to for more complicated fd leak tests.
++ </description>
++ <arg name="passer" type="object" interface="fd_passer"/>
++ </request>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++<!ELEMENT protocol (copyright?, description?, interface+)>
++ <!ATTLIST protocol name CDATA #REQUIRED>
++<!ELEMENT copyright (#PCDATA)>
++<!ELEMENT interface (description?,(request|event|enum)+)>
++ <!ATTLIST interface name CDATA #REQUIRED>
++ <!ATTLIST interface version CDATA #REQUIRED>
++<!ELEMENT request (description?,arg*)>
++ <!ATTLIST request name CDATA #REQUIRED>
++ <!ATTLIST request type CDATA #IMPLIED>
++ <!ATTLIST request since CDATA #IMPLIED>
++<!ELEMENT event (description?,arg*)>
++ <!ATTLIST event name CDATA #REQUIRED>
++ <!ATTLIST event type CDATA #IMPLIED>
++ <!ATTLIST event since CDATA #IMPLIED>
++<!ELEMENT enum (description?,entry*)>
++ <!ATTLIST enum name CDATA #REQUIRED>
++ <!ATTLIST enum since CDATA #IMPLIED>
++ <!ATTLIST enum bitfield CDATA #IMPLIED>
++<!ELEMENT entry (description?)>
++ <!ATTLIST entry name CDATA #REQUIRED>
++ <!ATTLIST entry value CDATA #REQUIRED>
++ <!ATTLIST entry summary CDATA #IMPLIED>
++ <!ATTLIST entry since CDATA #IMPLIED>
++<!ELEMENT arg (description?)>
++ <!ATTLIST arg name CDATA #REQUIRED>
++ <!ATTLIST arg type CDATA #REQUIRED>
++ <!ATTLIST arg summary CDATA #IMPLIED>
++ <!ATTLIST arg interface CDATA #IMPLIED>
++ <!ATTLIST arg allow-null CDATA #IMPLIED>
++ <!ATTLIST arg enum CDATA #IMPLIED>
++<!ELEMENT description (#PCDATA)>
++ <!ATTLIST description summary CDATA #REQUIRED>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="wayland">
++
++ <copyright>
++ Copyright © 2008-2011 Kristian Høgsberg
++ Copyright © 2010-2011 Intel Corporation
++ Copyright © 2012-2013 Collabora, Ltd.
++
++ Permission is hereby granted, free of charge, to any person
++ obtaining a copy of this software and associated documentation files
++ (the "Software"), to deal in the Software without restriction,
++ including without limitation the rights to use, copy, modify, merge,
++ publish, distribute, sublicense, and/or sell copies of the Software,
++ and to permit persons to whom the Software is furnished to do so,
++ subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the
++ next paragraph) shall be included in all copies or substantial
++ portions of the Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ SOFTWARE.
++ </copyright>
++
++ <interface name="wl_display" version="1">
++ <description summary="core global object">
++ The core global object. This is a special singleton object. It
++ is used for internal Wayland protocol features.
++ </description>
++
++ <request name="sync">
++ <description summary="asynchronous roundtrip">
++ The sync request asks the server to emit the 'done' event
++ on the returned wl_callback object. Since requests are
++ handled in-order and events are delivered in-order, this can
++ be used as a barrier to ensure all previous requests and the
++ resulting events have been handled.
++
++ The object returned by this request will be destroyed by the
++ compositor after the callback is fired and as such the client must not
++ attempt to use it after that point.
++
++ The callback_data passed in the callback is the event serial.
++ </description>
++ <arg name="callback" type="new_id" interface="wl_callback"
++ summary="callback object for the sync request"/>
++ </request>
++
++ <request name="get_registry">
++ <description summary="get global registry object">
++ This request creates a registry object that allows the client
++ to list and bind the global objects available from the
++ compositor.
++
++ It should be noted that the server side resources consumed in
++ response to a get_registry request can only be released when the
++ client disconnects, not when the client side proxy is destroyed.
++ Therefore, clients should invoke get_registry as infrequently as
++ possible to avoid wasting memory.
++ </description>
++ <arg name="registry" type="new_id" interface="wl_registry"
++ summary="global registry object"/>
++ </request>
++
++ <event name="error">
++ <description summary="fatal error event">
++ The error event is sent out when a fatal (non-recoverable)
++ error has occurred. The object_id argument is the object
++ where the error occurred, most often in response to a request
++ to that object. The code identifies the error and is defined
++ by the object interface. As such, each interface defines its
++ own set of error codes. The message is a brief description
++ of the error, for (debugging) convenience.
++ </description>
++ <arg name="object_id" type="object" summary="object where the error occurred"/>
++ <arg name="code" type="uint" summary="error code"/>
++ <arg name="message" type="string" summary="error description"/>
++ </event>
++
++ <enum name="error">
++ <description summary="global error values">
++ These errors are global and can be emitted in response to any
++ server request.
++ </description>
++ <entry name="invalid_object" value="0"
++ summary="server couldn't find object"/>
++ <entry name="invalid_method" value="1"
++ summary="method doesn't exist on the specified interface or malformed request"/>
++ <entry name="no_memory" value="2"
++ summary="server is out of memory"/>
++ <entry name="implementation" value="3"
++ summary="implementation error in compositor"/>
++ </enum>
++
++ <event name="delete_id">
++ <description summary="acknowledge object ID deletion">
++ This event is used internally by the object ID management
++ logic. When a client deletes an object that it had created,
++ the server will send this event to acknowledge that it has
++ seen the delete request. When the client receives this event,
++ it will know that it can safely reuse the object ID.
++ </description>
++ <arg name="id" type="uint" summary="deleted object ID"/>
++ </event>
++ </interface>
++
++ <interface name="wl_registry" version="1">
++ <description summary="global registry object">
++ The singleton global registry object. The server has a number of
++ global objects that are available to all clients. These objects
++ typically represent an actual object in the server (for example,
++ an input device) or they are singleton objects that provide
++ extension functionality.
++
++ When a client creates a registry object, the registry object
++ will emit a global event for each global currently in the
++ registry. Globals come and go as a result of device or
++ monitor hotplugs, reconfiguration or other events, and the
++ registry will send out global and global_remove events to
++ keep the client up to date with the changes. To mark the end
++ of the initial burst of events, the client can use the
++ wl_display.sync request immediately after calling
++ wl_display.get_registry.
++
++ A client can bind to a global object by using the bind
++ request. This creates a client-side handle that lets the object
++ emit events to the client and lets the client invoke requests on
++ the object.
++ </description>
++
++ <request name="bind">
++ <description summary="bind an object to the display">
++ Binds a new, client-created object to the server using the
++ specified name as the identifier.
++ </description>
++ <arg name="name" type="uint" summary="unique numeric name of the object"/>
++ <arg name="id" type="new_id" summary="bounded object"/>
++ </request>
++
++ <event name="global">
++ <description summary="announce global object">
++ Notify the client of global objects.
++
++ The event notifies the client that a global object with
++ the given name is now available, and it implements the
++ given version of the given interface.
++ </description>
++ <arg name="name" type="uint" summary="numeric name of the global object"/>
++ <arg name="interface" type="string" summary="interface implemented by the object"/>
++ <arg name="version" type="uint" summary="interface version"/>
++ </event>
++
++ <event name="global_remove">
++ <description summary="announce removal of global object">
++ Notify the client of removed global objects.
++
++ This event notifies the client that the global identified
++ by name is no longer available. If the client bound to
++ the global using the bind request, the client should now
++ destroy that object.
++
++ The object remains valid and requests to the object will be
++ ignored until the client destroys it, to avoid races between
++ the global going away and a client sending a request to it.
++ </description>
++ <arg name="name" type="uint" summary="numeric name of the global object"/>
++ </event>
++ </interface>
++
++ <interface name="wl_callback" version="1">
++ <description summary="callback object">
++ Clients can handle the 'done' event to get notified when
++ the related request is done.
++ </description>
++
++ <event name="done" type="destructor">
++ <description summary="done event">
++ Notify the client when the related request is done.
++ </description>
++ <arg name="callback_data" type="uint" summary="request-specific data for the callback"/>
++ </event>
++ </interface>
++
++ <interface name="wl_compositor" version="5">
++ <description summary="the compositor singleton">
++ A compositor. This object is a singleton global. The
++ compositor is in charge of combining the contents of multiple
++ surfaces into one displayable output.
++ </description>
++
++ <request name="create_surface">
++ <description summary="create new surface">
++ Ask the compositor to create a new surface.
++ </description>
++ <arg name="id" type="new_id" interface="wl_surface" summary="the new surface"/>
++ </request>
++
++ <request name="create_region">
++ <description summary="create new region">
++ Ask the compositor to create a new region.
++ </description>
++ <arg name="id" type="new_id" interface="wl_region" summary="the new region"/>
++ </request>
++ </interface>
++
++ <interface name="wl_shm_pool" version="1">
++ <description summary="a shared memory pool">
++ The wl_shm_pool object encapsulates a piece of memory shared
++ between the compositor and client. Through the wl_shm_pool
++ object, the client can allocate shared memory wl_buffer objects.
++ All objects created through the same pool share the same
++ underlying mapped memory. Reusing the mapped memory avoids the
++ setup/teardown overhead and is useful when interactively resizing
++ a surface or for many small buffers.
++ </description>
++
++ <request name="create_buffer">
++ <description summary="create a buffer from the pool">
++ Create a wl_buffer object from the pool.
++
++ The buffer is created offset bytes into the pool and has
++ width and height as specified. The stride argument specifies
++ the number of bytes from the beginning of one row to the beginning
++ of the next. The format is the pixel format of the buffer and
++ must be one of those advertised through the wl_shm.format event.
++
++ A buffer will keep a reference to the pool it was created from
++ so it is valid to destroy the pool immediately after creating
++ a buffer from it.
++ </description>
++ <arg name="id" type="new_id" interface="wl_buffer" summary="buffer to create"/>
++ <arg name="offset" type="int" summary="buffer byte offset within the pool"/>
++ <arg name="width" type="int" summary="buffer width, in pixels"/>
++ <arg name="height" type="int" summary="buffer height, in pixels"/>
++ <arg name="stride" type="int" summary="number of bytes from the beginning of one row to the beginning of the next row"/>
++ <arg name="format" type="uint" enum="wl_shm.format" summary="buffer pixel format"/>
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the pool">
++ Destroy the shared memory pool.
++
++ The mmapped memory will be released when all
++ buffers that have been created from this pool
++ are gone.
++ </description>
++ </request>
++
++ <request name="resize">
++ <description summary="change the size of the pool mapping">
++ This request will cause the server to remap the backing memory
++ for the pool from the file descriptor passed when the pool was
++ created, but using the new size. This request can only be
++ used to make the pool bigger.
++
++ This request only changes the amount of bytes that are mmapped
++ by the server and does not touch the file corresponding to the
++ file descriptor passed at creation time. It is the client's
++ responsibility to ensure that the file is at least as big as
++ the new pool size.
++ </description>
++ <arg name="size" type="int" summary="new size of the pool, in bytes"/>
++ </request>
++ </interface>
++
++ <interface name="wl_shm" version="1">
++ <description summary="shared memory support">
++ A singleton global object that provides support for shared
++ memory.
++
++ Clients can create wl_shm_pool objects using the create_pool
++ request.
++
++ On binding the wl_shm object one or more format events
++ are emitted to inform clients about the valid pixel formats
++ that can be used for buffers.
++ </description>
++
++ <enum name="error">
++ <description summary="wl_shm error values">
++ These errors can be emitted in response to wl_shm requests.
++ </description>
++ <entry name="invalid_format" value="0" summary="buffer format is not known"/>
++ <entry name="invalid_stride" value="1" summary="invalid size or stride during pool or buffer creation"/>
++ <entry name="invalid_fd" value="2" summary="mmapping the file descriptor failed"/>
++ </enum>
++
++ <enum name="format">
++ <description summary="pixel formats">
++ This describes the memory layout of an individual pixel.
++
++ All renderers should support argb8888 and xrgb8888 but any other
++ formats are optional and may not be supported by the particular
++ renderer in use.
++
++ The drm format codes match the macros defined in drm_fourcc.h, except
++ argb8888 and xrgb8888. The formats actually supported by the compositor
++ will be reported by the format event.
++
++ For all wl_shm formats and unless specified in another protocol
++ extension, pre-multiplied alpha is used for pixel values.
++ </description>
++ <!-- Note to protocol writers: don't update this list manually, instead
++ run the automated script that keeps it in sync with drm_fourcc.h. -->
++ <entry name="argb8888" value="0" summary="32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian"/>
++ <entry name="xrgb8888" value="1" summary="32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian"/>
++ <entry name="c8" value="0x20203843" summary="8-bit color index format, [7:0] C"/>
++ <entry name="rgb332" value="0x38424752" summary="8-bit RGB format, [7:0] R:G:B 3:3:2"/>
++ <entry name="bgr233" value="0x38524742" summary="8-bit BGR format, [7:0] B:G:R 2:3:3"/>
++ <entry name="xrgb4444" value="0x32315258" summary="16-bit xRGB format, [15:0] x:R:G:B 4:4:4:4 little endian"/>
++ <entry name="xbgr4444" value="0x32314258" summary="16-bit xBGR format, [15:0] x:B:G:R 4:4:4:4 little endian"/>
++ <entry name="rgbx4444" value="0x32315852" summary="16-bit RGBx format, [15:0] R:G:B:x 4:4:4:4 little endian"/>
++ <entry name="bgrx4444" value="0x32315842" summary="16-bit BGRx format, [15:0] B:G:R:x 4:4:4:4 little endian"/>
++ <entry name="argb4444" value="0x32315241" summary="16-bit ARGB format, [15:0] A:R:G:B 4:4:4:4 little endian"/>
++ <entry name="abgr4444" value="0x32314241" summary="16-bit ABGR format, [15:0] A:B:G:R 4:4:4:4 little endian"/>
++ <entry name="rgba4444" value="0x32314152" summary="16-bit RBGA format, [15:0] R:G:B:A 4:4:4:4 little endian"/>
++ <entry name="bgra4444" value="0x32314142" summary="16-bit BGRA format, [15:0] B:G:R:A 4:4:4:4 little endian"/>
++ <entry name="xrgb1555" value="0x35315258" summary="16-bit xRGB format, [15:0] x:R:G:B 1:5:5:5 little endian"/>
++ <entry name="xbgr1555" value="0x35314258" summary="16-bit xBGR 1555 format, [15:0] x:B:G:R 1:5:5:5 little endian"/>
++ <entry name="rgbx5551" value="0x35315852" summary="16-bit RGBx 5551 format, [15:0] R:G:B:x 5:5:5:1 little endian"/>
++ <entry name="bgrx5551" value="0x35315842" summary="16-bit BGRx 5551 format, [15:0] B:G:R:x 5:5:5:1 little endian"/>
++ <entry name="argb1555" value="0x35315241" summary="16-bit ARGB 1555 format, [15:0] A:R:G:B 1:5:5:5 little endian"/>
++ <entry name="abgr1555" value="0x35314241" summary="16-bit ABGR 1555 format, [15:0] A:B:G:R 1:5:5:5 little endian"/>
++ <entry name="rgba5551" value="0x35314152" summary="16-bit RGBA 5551 format, [15:0] R:G:B:A 5:5:5:1 little endian"/>
++ <entry name="bgra5551" value="0x35314142" summary="16-bit BGRA 5551 format, [15:0] B:G:R:A 5:5:5:1 little endian"/>
++ <entry name="rgb565" value="0x36314752" summary="16-bit RGB 565 format, [15:0] R:G:B 5:6:5 little endian"/>
++ <entry name="bgr565" value="0x36314742" summary="16-bit BGR 565 format, [15:0] B:G:R 5:6:5 little endian"/>
++ <entry name="rgb888" value="0x34324752" summary="24-bit RGB format, [23:0] R:G:B little endian"/>
++ <entry name="bgr888" value="0x34324742" summary="24-bit BGR format, [23:0] B:G:R little endian"/>
++ <entry name="xbgr8888" value="0x34324258" summary="32-bit xBGR format, [31:0] x:B:G:R 8:8:8:8 little endian"/>
++ <entry name="rgbx8888" value="0x34325852" summary="32-bit RGBx format, [31:0] R:G:B:x 8:8:8:8 little endian"/>
++ <entry name="bgrx8888" value="0x34325842" summary="32-bit BGRx format, [31:0] B:G:R:x 8:8:8:8 little endian"/>
++ <entry name="abgr8888" value="0x34324241" summary="32-bit ABGR format, [31:0] A:B:G:R 8:8:8:8 little endian"/>
++ <entry name="rgba8888" value="0x34324152" summary="32-bit RGBA format, [31:0] R:G:B:A 8:8:8:8 little endian"/>
++ <entry name="bgra8888" value="0x34324142" summary="32-bit BGRA format, [31:0] B:G:R:A 8:8:8:8 little endian"/>
++ <entry name="xrgb2101010" value="0x30335258" summary="32-bit xRGB format, [31:0] x:R:G:B 2:10:10:10 little endian"/>
++ <entry name="xbgr2101010" value="0x30334258" summary="32-bit xBGR format, [31:0] x:B:G:R 2:10:10:10 little endian"/>
++ <entry name="rgbx1010102" value="0x30335852" summary="32-bit RGBx format, [31:0] R:G:B:x 10:10:10:2 little endian"/>
++ <entry name="bgrx1010102" value="0x30335842" summary="32-bit BGRx format, [31:0] B:G:R:x 10:10:10:2 little endian"/>
++ <entry name="argb2101010" value="0x30335241" summary="32-bit ARGB format, [31:0] A:R:G:B 2:10:10:10 little endian"/>
++ <entry name="abgr2101010" value="0x30334241" summary="32-bit ABGR format, [31:0] A:B:G:R 2:10:10:10 little endian"/>
++ <entry name="rgba1010102" value="0x30334152" summary="32-bit RGBA format, [31:0] R:G:B:A 10:10:10:2 little endian"/>
++ <entry name="bgra1010102" value="0x30334142" summary="32-bit BGRA format, [31:0] B:G:R:A 10:10:10:2 little endian"/>
++ <entry name="yuyv" value="0x56595559" summary="packed YCbCr format, [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian"/>
++ <entry name="yvyu" value="0x55595659" summary="packed YCbCr format, [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian"/>
++ <entry name="uyvy" value="0x59565955" summary="packed YCbCr format, [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian"/>
++ <entry name="vyuy" value="0x59555956" summary="packed YCbCr format, [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian"/>
++ <entry name="ayuv" value="0x56555941" summary="packed AYCbCr format, [31:0] A:Y:Cb:Cr 8:8:8:8 little endian"/>
++ <entry name="nv12" value="0x3231564e" summary="2 plane YCbCr Cr:Cb format, 2x2 subsampled Cr:Cb plane"/>
++ <entry name="nv21" value="0x3132564e" summary="2 plane YCbCr Cb:Cr format, 2x2 subsampled Cb:Cr plane"/>
++ <entry name="nv16" value="0x3631564e" summary="2 plane YCbCr Cr:Cb format, 2x1 subsampled Cr:Cb plane"/>
++ <entry name="nv61" value="0x3136564e" summary="2 plane YCbCr Cb:Cr format, 2x1 subsampled Cb:Cr plane"/>
++ <entry name="yuv410" value="0x39565559" summary="3 plane YCbCr format, 4x4 subsampled Cb (1) and Cr (2) planes"/>
++ <entry name="yvu410" value="0x39555659" summary="3 plane YCbCr format, 4x4 subsampled Cr (1) and Cb (2) planes"/>
++ <entry name="yuv411" value="0x31315559" summary="3 plane YCbCr format, 4x1 subsampled Cb (1) and Cr (2) planes"/>
++ <entry name="yvu411" value="0x31315659" summary="3 plane YCbCr format, 4x1 subsampled Cr (1) and Cb (2) planes"/>
++ <entry name="yuv420" value="0x32315559" summary="3 plane YCbCr format, 2x2 subsampled Cb (1) and Cr (2) planes"/>
++ <entry name="yvu420" value="0x32315659" summary="3 plane YCbCr format, 2x2 subsampled Cr (1) and Cb (2) planes"/>
++ <entry name="yuv422" value="0x36315559" summary="3 plane YCbCr format, 2x1 subsampled Cb (1) and Cr (2) planes"/>
++ <entry name="yvu422" value="0x36315659" summary="3 plane YCbCr format, 2x1 subsampled Cr (1) and Cb (2) planes"/>
++ <entry name="yuv444" value="0x34325559" summary="3 plane YCbCr format, non-subsampled Cb (1) and Cr (2) planes"/>
++ <entry name="yvu444" value="0x34325659" summary="3 plane YCbCr format, non-subsampled Cr (1) and Cb (2) planes"/>
++ <entry name="r8" value="0x20203852" summary="[7:0] R"/>
++ <entry name="r16" value="0x20363152" summary="[15:0] R little endian"/>
++ <entry name="rg88" value="0x38384752" summary="[15:0] R:G 8:8 little endian"/>
++ <entry name="gr88" value="0x38385247" summary="[15:0] G:R 8:8 little endian"/>
++ <entry name="rg1616" value="0x32334752" summary="[31:0] R:G 16:16 little endian"/>
++ <entry name="gr1616" value="0x32335247" summary="[31:0] G:R 16:16 little endian"/>
++ <entry name="xrgb16161616f" value="0x48345258" summary="[63:0] x:R:G:B 16:16:16:16 little endian"/>
++ <entry name="xbgr16161616f" value="0x48344258" summary="[63:0] x:B:G:R 16:16:16:16 little endian"/>
++ <entry name="argb16161616f" value="0x48345241" summary="[63:0] A:R:G:B 16:16:16:16 little endian"/>
++ <entry name="abgr16161616f" value="0x48344241" summary="[63:0] A:B:G:R 16:16:16:16 little endian"/>
++ <entry name="xyuv8888" value="0x56555958" summary="[31:0] X:Y:Cb:Cr 8:8:8:8 little endian"/>
++ <entry name="vuy888" value="0x34325556" summary="[23:0] Cr:Cb:Y 8:8:8 little endian"/>
++ <entry name="vuy101010" value="0x30335556" summary="Y followed by U then V, 10:10:10. Non-linear modifier only"/>
++ <entry name="y210" value="0x30313259" summary="[63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 10:6:10:6:10:6:10:6 little endian per 2 Y pixels"/>
++ <entry name="y212" value="0x32313259" summary="[63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 12:4:12:4:12:4:12:4 little endian per 2 Y pixels"/>
++ <entry name="y216" value="0x36313259" summary="[63:0] Cr0:Y1:Cb0:Y0 16:16:16:16 little endian per 2 Y pixels"/>
++ <entry name="y410" value="0x30313459" summary="[31:0] A:Cr:Y:Cb 2:10:10:10 little endian"/>
++ <entry name="y412" value="0x32313459" summary="[63:0] A:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian"/>
++ <entry name="y416" value="0x36313459" summary="[63:0] A:Cr:Y:Cb 16:16:16:16 little endian"/>
++ <entry name="xvyu2101010" value="0x30335658" summary="[31:0] X:Cr:Y:Cb 2:10:10:10 little endian"/>
++ <entry name="xvyu12_16161616" value="0x36335658" summary="[63:0] X:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian"/>
++ <entry name="xvyu16161616" value="0x38345658" summary="[63:0] X:Cr:Y:Cb 16:16:16:16 little endian"/>
++ <entry name="y0l0" value="0x304c3059" summary="[63:0] A3:A2:Y3:0:Cr0:0:Y2:0:A1:A0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian"/>
++ <entry name="x0l0" value="0x304c3058" summary="[63:0] X3:X2:Y3:0:Cr0:0:Y2:0:X1:X0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian"/>
++ <entry name="y0l2" value="0x324c3059" summary="[63:0] A3:A2:Y3:Cr0:Y2:A1:A0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian"/>
++ <entry name="x0l2" value="0x324c3058" summary="[63:0] X3:X2:Y3:Cr0:Y2:X1:X0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian"/>
++ <entry name="yuv420_8bit" value="0x38305559"/>
++ <entry name="yuv420_10bit" value="0x30315559"/>
++ <entry name="xrgb8888_a8" value="0x38415258"/>
++ <entry name="xbgr8888_a8" value="0x38414258"/>
++ <entry name="rgbx8888_a8" value="0x38415852"/>
++ <entry name="bgrx8888_a8" value="0x38415842"/>
++ <entry name="rgb888_a8" value="0x38413852"/>
++ <entry name="bgr888_a8" value="0x38413842"/>
++ <entry name="rgb565_a8" value="0x38413552"/>
++ <entry name="bgr565_a8" value="0x38413542"/>
++ <entry name="nv24" value="0x3432564e" summary="non-subsampled Cr:Cb plane"/>
++ <entry name="nv42" value="0x3234564e" summary="non-subsampled Cb:Cr plane"/>
++ <entry name="p210" value="0x30313250" summary="2x1 subsampled Cr:Cb plane, 10 bit per channel"/>
++ <entry name="p010" value="0x30313050" summary="2x2 subsampled Cr:Cb plane 10 bits per channel"/>
++ <entry name="p012" value="0x32313050" summary="2x2 subsampled Cr:Cb plane 12 bits per channel"/>
++ <entry name="p016" value="0x36313050" summary="2x2 subsampled Cr:Cb plane 16 bits per channel"/>
++ <entry name="axbxgxrx106106106106" value="0x30314241" summary="[63:0] A:x:B:x:G:x:R:x 10:6:10:6:10:6:10:6 little endian"/>
++ <entry name="nv15" value="0x3531564e" summary="2x2 subsampled Cr:Cb plane"/>
++ <entry name="q410" value="0x30313451"/>
++ <entry name="q401" value="0x31303451"/>
++ <entry name="xrgb16161616" value="0x38345258" summary="[63:0] x:R:G:B 16:16:16:16 little endian"/>
++ <entry name="xbgr16161616" value="0x38344258" summary="[63:0] x:B:G:R 16:16:16:16 little endian"/>
++ <entry name="argb16161616" value="0x38345241" summary="[63:0] A:R:G:B 16:16:16:16 little endian"/>
++ <entry name="abgr16161616" value="0x38344241" summary="[63:0] A:B:G:R 16:16:16:16 little endian"/>
++ </enum>
++
++ <request name="create_pool">
++ <description summary="create a shm pool">
++ Create a new wl_shm_pool object.
++
++ The pool can be used to create shared memory based buffer
++ objects. The server will mmap size bytes of the passed file
++ descriptor, to use as backing memory for the pool.
++ </description>
++ <arg name="id" type="new_id" interface="wl_shm_pool" summary="pool to create"/>
++ <arg name="fd" type="fd" summary="file descriptor for the pool"/>
++ <arg name="size" type="int" summary="pool size, in bytes"/>
++ </request>
++
++ <event name="format">
++ <description summary="pixel format description">
++ Informs the client about a valid pixel format that
++ can be used for buffers. Known formats include
++ argb8888 and xrgb8888.
++ </description>
++ <arg name="format" type="uint" enum="format" summary="buffer pixel format"/>
++ </event>
++ </interface>
++
++ <interface name="wl_buffer" version="1">
++ <description summary="content for a wl_surface">
++ A buffer provides the content for a wl_surface. Buffers are
++ created through factory interfaces such as wl_shm, wp_linux_buffer_params
++ (from the linux-dmabuf protocol extension) or similar. It has a width and
++ a height and can be attached to a wl_surface, but the mechanism by which a
++ client provides and updates the contents is defined by the buffer factory
++ interface.
++
++ If the buffer uses a format that has an alpha channel, the alpha channel
++ is assumed to be premultiplied in the color channels unless otherwise
++ specified.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy a buffer">
++ Destroy a buffer. If and how you need to release the backing
++ storage is defined by the buffer factory interface.
++
++ For possible side-effects to a surface, see wl_surface.attach.
++ </description>
++ </request>
++
++ <event name="release">
++ <description summary="compositor releases buffer">
++ Sent when this wl_buffer is no longer used by the compositor.
++ The client is now free to reuse or destroy this buffer and its
++ backing storage.
++
++ If a client receives a release event before the frame callback
++ requested in the same wl_surface.commit that attaches this
++ wl_buffer to a surface, then the client is immediately free to
++ reuse the buffer and its backing storage, and does not need a
++ second buffer for the next surface content update. Typically
++ this is possible, when the compositor maintains a copy of the
++ wl_surface contents, e.g. as a GL texture. This is an important
++ optimization for GL(ES) compositors with wl_shm clients.
++ </description>
++ </event>
++ </interface>
++
++ <interface name="wl_data_offer" version="3">
++ <description summary="offer to transfer data">
++ A wl_data_offer represents a piece of data offered for transfer
++ by another client (the source client). It is used by the
++ copy-and-paste and drag-and-drop mechanisms. The offer
++ describes the different mime types that the data can be
++ converted to and provides the mechanism for transferring the
++ data directly from the source client.
++ </description>
++
++ <enum name="error">
++ <entry name="invalid_finish" value="0"
++ summary="finish request was called untimely"/>
++ <entry name="invalid_action_mask" value="1"
++ summary="action mask contains invalid values"/>
++ <entry name="invalid_action" value="2"
++ summary="action argument has an invalid value"/>
++ <entry name="invalid_offer" value="3"
++ summary="offer doesn't accept this request"/>
++ </enum>
++
++ <request name="accept">
++ <description summary="accept one of the offered mime types">
++ Indicate that the client can accept the given mime type, or
++ NULL for not accepted.
++
++ For objects of version 2 or older, this request is used by the
++ client to give feedback whether the client can receive the given
++ mime type, or NULL if none is accepted; the feedback does not
++ determine whether the drag-and-drop operation succeeds or not.
++
++ For objects of version 3 or newer, this request determines the
++ final result of the drag-and-drop operation. If the end result
++ is that no mime types were accepted, the drag-and-drop operation
++ will be cancelled and the corresponding drag source will receive
++ wl_data_source.cancelled. Clients may still use this event in
++ conjunction with wl_data_source.action for feedback.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the accept request"/>
++ <arg name="mime_type" type="string" allow-null="true" summary="mime type accepted by the client"/>
++ </request>
++
++ <request name="receive">
++ <description summary="request that the data is transferred">
++ To transfer the offered data, the client issues this request
++ and indicates the mime type it wants to receive. The transfer
++ happens through the passed file descriptor (typically created
++ with the pipe system call). The source client writes the data
++ in the mime type representation requested and then closes the
++ file descriptor.
++
++ The receiving client reads from the read end of the pipe until
++ EOF and then closes its end, at which point the transfer is
++ complete.
++
++ This request may happen multiple times for different mime types,
++ both before and after wl_data_device.drop. Drag-and-drop destination
++ clients may preemptively fetch data or examine it more closely to
++ determine acceptance.
++ </description>
++ <arg name="mime_type" type="string" summary="mime type desired by receiver"/>
++ <arg name="fd" type="fd" summary="file descriptor for data transfer"/>
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy data offer">
++ Destroy the data offer.
++ </description>
++ </request>
++
++ <event name="offer">
++ <description summary="advertise offered mime type">
++ Sent immediately after creating the wl_data_offer object. One
++ event per offered mime type.
++ </description>
++ <arg name="mime_type" type="string" summary="offered mime type"/>
++ </event>
++
++ <!-- Version 3 additions -->
++
++ <request name="finish" since="3">
++ <description summary="the offer will no longer be used">
++ Notifies the compositor that the drag destination successfully
++ finished the drag-and-drop operation.
++
++ Upon receiving this request, the compositor will emit
++ wl_data_source.dnd_finished on the drag source client.
++
++ It is a client error to perform other requests than
++ wl_data_offer.destroy after this one. It is also an error to perform
++ this request after a NULL mime type has been set in
++ wl_data_offer.accept or no action was received through
++ wl_data_offer.action.
++
++ If wl_data_offer.finish request is received for a non drag and drop
++ operation, the invalid_finish protocol error is raised.
++ </description>
++ </request>
++
++ <request name="set_actions" since="3">
++ <description summary="set the available/preferred drag-and-drop actions">
++ Sets the actions that the destination side client supports for
++ this operation. This request may trigger the emission of
++ wl_data_source.action and wl_data_offer.action events if the compositor
++ needs to change the selected action.
++
++ This request can be called multiple times throughout the
++ drag-and-drop operation, typically in response to wl_data_device.enter
++ or wl_data_device.motion events.
++
++ This request determines the final result of the drag-and-drop
++ operation. If the end result is that no action is accepted,
++ the drag source will receive wl_data_source.cancelled.
++
++ The dnd_actions argument must contain only values expressed in the
++ wl_data_device_manager.dnd_actions enum, and the preferred_action
++ argument must only contain one of those values set, otherwise it
++ will result in a protocol error.
++
++ While managing an "ask" action, the destination drag-and-drop client
++ may perform further wl_data_offer.receive requests, and is expected
++ to perform one last wl_data_offer.set_actions request with a preferred
++ action other than "ask" (and optionally wl_data_offer.accept) before
++ requesting wl_data_offer.finish, in order to convey the action selected
++ by the user. If the preferred action is not in the
++ wl_data_offer.source_actions mask, an error will be raised.
++
++ If the "ask" action is dismissed (e.g. user cancellation), the client
++ is expected to perform wl_data_offer.destroy right away.
++
++ This request can only be made on drag-and-drop offers, a protocol error
++ will be raised otherwise.
++ </description>
++ <arg name="dnd_actions" type="uint" summary="actions supported by the destination client"
++ enum="wl_data_device_manager.dnd_action"/>
++ <arg name="preferred_action" type="uint" summary="action preferred by the destination client"
++ enum="wl_data_device_manager.dnd_action"/>
++ </request>
++
++ <event name="source_actions" since="3">
++ <description summary="notify the source-side available actions">
++ This event indicates the actions offered by the data source. It
++ will be sent right after wl_data_device.enter, or anytime the source
++ side changes its offered actions through wl_data_source.set_actions.
++ </description>
++ <arg name="source_actions" type="uint" summary="actions offered by the data source"
++ enum="wl_data_device_manager.dnd_action"/>
++ </event>
++
++ <event name="action" since="3">
++ <description summary="notify the selected action">
++ This event indicates the action selected by the compositor after
++ matching the source/destination side actions. Only one action (or
++ none) will be offered here.
++
++ This event can be emitted multiple times during the drag-and-drop
++ operation in response to destination side action changes through
++ wl_data_offer.set_actions.
++
++ This event will no longer be emitted after wl_data_device.drop
++ happened on the drag-and-drop destination, the client must
++ honor the last action received, or the last preferred one set
++ through wl_data_offer.set_actions when handling an "ask" action.
++
++ Compositors may also change the selected action on the fly, mainly
++ in response to keyboard modifier changes during the drag-and-drop
++ operation.
++
++ The most recent action received is always the valid one. Prior to
++ receiving wl_data_device.drop, the chosen action may change (e.g.
++ due to keyboard modifiers being pressed). At the time of receiving
++ wl_data_device.drop the drag-and-drop destination must honor the
++ last action received.
++
++ Action changes may still happen after wl_data_device.drop,
++ especially on "ask" actions, where the drag-and-drop destination
++ may choose another action afterwards. Action changes happening
++ at this stage are always the result of inter-client negotiation, the
++ compositor shall no longer be able to induce a different action.
++
++ Upon "ask" actions, it is expected that the drag-and-drop destination
++ may potentially choose a different action and/or mime type,
++ based on wl_data_offer.source_actions and finally chosen by the
++ user (e.g. popping up a menu with the available options). The
++ final wl_data_offer.set_actions and wl_data_offer.accept requests
++ must happen before the call to wl_data_offer.finish.
++ </description>
++ <arg name="dnd_action" type="uint" summary="action selected by the compositor"
++ enum="wl_data_device_manager.dnd_action"/>
++ </event>
++ </interface>
++
++ <interface name="wl_data_source" version="3">
++ <description summary="offer to transfer data">
++ The wl_data_source object is the source side of a wl_data_offer.
++ It is created by the source client in a data transfer and
++ provides a way to describe the offered data and a way to respond
++ to requests to transfer the data.
++ </description>
++
++ <enum name="error">
++ <entry name="invalid_action_mask" value="0"
++ summary="action mask contains invalid values"/>
++ <entry name="invalid_source" value="1"
++ summary="source doesn't accept this request"/>
++ </enum>
++
++ <request name="offer">
++ <description summary="add an offered mime type">
++ This request adds a mime type to the set of mime types
++ advertised to targets. Can be called several times to offer
++ multiple types.
++ </description>
++ <arg name="mime_type" type="string" summary="mime type offered by the data source"/>
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the data source">
++ Destroy the data source.
++ </description>
++ </request>
++
++ <event name="target">
++ <description summary="a target accepts an offered mime type">
++ Sent when a target accepts pointer_focus or motion events. If
++ a target does not accept any of the offered types, type is NULL.
++
++ Used for feedback during drag-and-drop.
++ </description>
++ <arg name="mime_type" type="string" allow-null="true" summary="mime type accepted by the target"/>
++ </event>
++
++ <event name="send">
++ <description summary="send the data">
++ Request for data from the client. Send the data as the
++ specified mime type over the passed file descriptor, then
++ close it.
++ </description>
++ <arg name="mime_type" type="string" summary="mime type for the data"/>
++ <arg name="fd" type="fd" summary="file descriptor for the data"/>
++ </event>
++
++ <event name="cancelled">
++ <description summary="selection was cancelled">
++ This data source is no longer valid. There are several reasons why
++ this could happen:
++
++ - The data source has been replaced by another data source.
++ - The drag-and-drop operation was performed, but the drop destination
++ did not accept any of the mime types offered through
++ wl_data_source.target.
++ - The drag-and-drop operation was performed, but the drop destination
++ did not select any of the actions present in the mask offered through
++ wl_data_source.action.
++ - The drag-and-drop operation was performed but didn't happen over a
++ surface.
++ - The compositor cancelled the drag-and-drop operation (e.g. compositor
++ dependent timeouts to avoid stale drag-and-drop transfers).
++
++ The client should clean up and destroy this data source.
++
++ For objects of version 2 or older, wl_data_source.cancelled will
++ only be emitted if the data source was replaced by another data
++ source.
++ </description>
++ </event>
++
++ <!-- Version 3 additions -->
++
++ <request name="set_actions" since="3">
++ <description summary="set the available drag-and-drop actions">
++ Sets the actions that the source side client supports for this
++ operation. This request may trigger wl_data_source.action and
++ wl_data_offer.action events if the compositor needs to change the
++ selected action.
++
++ The dnd_actions argument must contain only values expressed in the
++ wl_data_device_manager.dnd_actions enum, otherwise it will result
++ in a protocol error.
++
++ This request must be made once only, and can only be made on sources
++ used in drag-and-drop, so it must be performed before
++ wl_data_device.start_drag. Attempting to use the source other than
++ for drag-and-drop will raise a protocol error.
++ </description>
++ <arg name="dnd_actions" type="uint" summary="actions supported by the data source"
++ enum="wl_data_device_manager.dnd_action"/>
++ </request>
++
++ <event name="dnd_drop_performed" since="3">
++ <description summary="the drag-and-drop operation physically finished">
++ The user performed the drop action. This event does not indicate
++ acceptance, wl_data_source.cancelled may still be emitted afterwards
++ if the drop destination does not accept any mime type.
++
++ However, this event might however not be received if the compositor
++ cancelled the drag-and-drop operation before this event could happen.
++
++ Note that the data_source may still be used in the future and should
++ not be destroyed here.
++ </description>
++ </event>
++
++ <event name="dnd_finished" since="3">
++ <description summary="the drag-and-drop operation concluded">
++ The drop destination finished interoperating with this data
++ source, so the client is now free to destroy this data source and
++ free all associated data.
++
++ If the action used to perform the operation was "move", the
++ source can now delete the transferred data.
++ </description>
++ </event>
++
++ <event name="action" since="3">
++ <description summary="notify the selected action">
++ This event indicates the action selected by the compositor after
++ matching the source/destination side actions. Only one action (or
++ none) will be offered here.
++
++ This event can be emitted multiple times during the drag-and-drop
++ operation, mainly in response to destination side changes through
++ wl_data_offer.set_actions, and as the data device enters/leaves
++ surfaces.
++
++ It is only possible to receive this event after
++ wl_data_source.dnd_drop_performed if the drag-and-drop operation
++ ended in an "ask" action, in which case the final wl_data_source.action
++ event will happen immediately before wl_data_source.dnd_finished.
++
++ Compositors may also change the selected action on the fly, mainly
++ in response to keyboard modifier changes during the drag-and-drop
++ operation.
++
++ The most recent action received is always the valid one. The chosen
++ action may change alongside negotiation (e.g. an "ask" action can turn
++ into a "move" operation), so the effects of the final action must
++ always be applied in wl_data_offer.dnd_finished.
++
++ Clients can trigger cursor surface changes from this point, so
++ they reflect the current action.
++ </description>
++ <arg name="dnd_action" type="uint" summary="action selected by the compositor"
++ enum="wl_data_device_manager.dnd_action"/>
++ </event>
++ </interface>
++
++ <interface name="wl_data_device" version="3">
++ <description summary="data transfer device">
++ There is one wl_data_device per seat which can be obtained
++ from the global wl_data_device_manager singleton.
++
++ A wl_data_device provides access to inter-client data transfer
++ mechanisms such as copy-and-paste and drag-and-drop.
++ </description>
++
++ <enum name="error">
++ <entry name="role" value="0" summary="given wl_surface has another role"/>
++ </enum>
++
++ <request name="start_drag">
++ <description summary="start drag-and-drop operation">
++ This request asks the compositor to start a drag-and-drop
++ operation on behalf of the client.
++
++ The source argument is the data source that provides the data
++ for the eventual data transfer. If source is NULL, enter, leave
++ and motion events are sent only to the client that initiated the
++ drag and the client is expected to handle the data passing
++ internally. If source is destroyed, the drag-and-drop session will be
++ cancelled.
++
++ The origin surface is the surface where the drag originates and
++ the client must have an active implicit grab that matches the
++ serial.
++
++ The icon surface is an optional (can be NULL) surface that
++ provides an icon to be moved around with the cursor. Initially,
++ the top-left corner of the icon surface is placed at the cursor
++ hotspot, but subsequent wl_surface.attach request can move the
++ relative position. Attach requests must be confirmed with
++ wl_surface.commit as usual. The icon surface is given the role of
++ a drag-and-drop icon. If the icon surface already has another role,
++ it raises a protocol error.
++
++ The current and pending input regions of the icon wl_surface are
++ cleared, and wl_surface.set_input_region is ignored until the
++ wl_surface is no longer used as the icon surface. When the use
++ as an icon ends, the current and pending input regions become
++ undefined, and the wl_surface is unmapped.
++ </description>
++ <arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the eventual transfer"/>
++ <arg name="origin" type="object" interface="wl_surface" summary="surface where the drag originates"/>
++ <arg name="icon" type="object" interface="wl_surface" allow-null="true" summary="drag-and-drop icon surface"/>
++ <arg name="serial" type="uint" summary="serial number of the implicit grab on the origin"/>
++ </request>
++
++ <request name="set_selection">
++ <description summary="copy data to the selection">
++ This request asks the compositor to set the selection
++ to the data from the source on behalf of the client.
++
++ To unset the selection, set the source to NULL.
++ </description>
++ <arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the selection"/>
++ <arg name="serial" type="uint" summary="serial number of the event that triggered this request"/>
++ </request>
++
++ <event name="data_offer">
++ <description summary="introduce a new wl_data_offer">
++ The data_offer event introduces a new wl_data_offer object,
++ which will subsequently be used in either the
++ data_device.enter event (for drag-and-drop) or the
++ data_device.selection event (for selections). Immediately
++ following the data_device.data_offer event, the new data_offer
++ object will send out data_offer.offer events to describe the
++ mime types it offers.
++ </description>
++ <arg name="id" type="new_id" interface="wl_data_offer" summary="the new data_offer object"/>
++ </event>
++
++ <event name="enter">
++ <description summary="initiate drag-and-drop session">
++ This event is sent when an active drag-and-drop pointer enters
++ a surface owned by the client. The position of the pointer at
++ enter time is provided by the x and y arguments, in surface-local
++ coordinates.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the enter event"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="client surface entered"/>
++ <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++ <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++ <arg name="id" type="object" interface="wl_data_offer" allow-null="true"
++ summary="source data_offer object"/>
++ </event>
++
++ <event name="leave">
++ <description summary="end drag-and-drop session">
++ This event is sent when the drag-and-drop pointer leaves the
++ surface and the session ends. The client must destroy the
++ wl_data_offer introduced at enter time at this point.
++ </description>
++ </event>
++
++ <event name="motion">
++ <description summary="drag-and-drop session motion">
++ This event is sent when the drag-and-drop pointer moves within
++ the currently focused surface. The new position of the pointer
++ is provided by the x and y arguments, in surface-local
++ coordinates.
++ </description>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++ <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++ </event>
++
++ <event name="drop">
++ <description summary="end drag-and-drop session successfully">
++ The event is sent when a drag-and-drop operation is ended
++ because the implicit grab is removed.
++
++ The drag-and-drop destination is expected to honor the last action
++ received through wl_data_offer.action, if the resulting action is
++ "copy" or "move", the destination can still perform
++ wl_data_offer.receive requests, and is expected to end all
++ transfers with a wl_data_offer.finish request.
++
++ If the resulting action is "ask", the action will not be considered
++ final. The drag-and-drop destination is expected to perform one last
++ wl_data_offer.set_actions request, or wl_data_offer.destroy in order
++ to cancel the operation.
++ </description>
++ </event>
++
++ <event name="selection">
++ <description summary="advertise new selection">
++ The selection event is sent out to notify the client of a new
++ wl_data_offer for the selection for this device. The
++ data_device.data_offer and the data_offer.offer events are
++ sent out immediately before this event to introduce the data
++ offer object. The selection event is sent to a client
++ immediately before receiving keyboard focus and when a new
++ selection is set while the client has keyboard focus. The
++ data_offer is valid until a new data_offer or NULL is received
++ or until the client loses keyboard focus. Switching surface with
++ keyboard focus within the same client doesn't mean a new selection
++ will be sent. The client must destroy the previous selection
++ data_offer, if any, upon receiving this event.
++ </description>
++ <arg name="id" type="object" interface="wl_data_offer" allow-null="true"
++ summary="selection data_offer object"/>
++ </event>
++
++ <!-- Version 2 additions -->
++
++ <request name="release" type="destructor" since="2">
++ <description summary="destroy data device">
++ This request destroys the data device.
++ </description>
++ </request>
++ </interface>
++
++ <interface name="wl_data_device_manager" version="3">
++ <description summary="data transfer interface">
++ The wl_data_device_manager is a singleton global object that
++ provides access to inter-client data transfer mechanisms such as
++ copy-and-paste and drag-and-drop. These mechanisms are tied to
++ a wl_seat and this interface lets a client get a wl_data_device
++ corresponding to a wl_seat.
++
++ Depending on the version bound, the objects created from the bound
++ wl_data_device_manager object will have different requirements for
++ functioning properly. See wl_data_source.set_actions,
++ wl_data_offer.accept and wl_data_offer.finish for details.
++ </description>
++
++ <request name="create_data_source">
++ <description summary="create a new data source">
++ Create a new data source.
++ </description>
++ <arg name="id" type="new_id" interface="wl_data_source" summary="data source to create"/>
++ </request>
++
++ <request name="get_data_device">
++ <description summary="create a new data device">
++ Create a new data device for a given seat.
++ </description>
++ <arg name="id" type="new_id" interface="wl_data_device" summary="data device to create"/>
++ <arg name="seat" type="object" interface="wl_seat" summary="seat associated with the data device"/>
++ </request>
++
++ <!-- Version 3 additions -->
++
++ <enum name="dnd_action" bitfield="true" since="3">
++ <description summary="drag and drop actions">
++ This is a bitmask of the available/preferred actions in a
++ drag-and-drop operation.
++
++ In the compositor, the selected action is a result of matching the
++ actions offered by the source and destination sides. "action" events
++ with a "none" action will be sent to both source and destination if
++ there is no match. All further checks will effectively happen on
++ (source actions ∩ destination actions).
++
++ In addition, compositors may also pick different actions in
++ reaction to key modifiers being pressed. One common design that
++ is used in major toolkits (and the behavior recommended for
++ compositors) is:
++
++ - If no modifiers are pressed, the first match (in bit order)
++ will be used.
++ - Pressing Shift selects "move", if enabled in the mask.
++ - Pressing Control selects "copy", if enabled in the mask.
++
++ Behavior beyond that is considered implementation-dependent.
++ Compositors may for example bind other modifiers (like Alt/Meta)
++ or drags initiated with other buttons than BTN_LEFT to specific
++ actions (e.g. "ask").
++ </description>
++ <entry name="none" value="0" summary="no action"/>
++ <entry name="copy" value="1" summary="copy action"/>
++ <entry name="move" value="2" summary="move action"/>
++ <entry name="ask" value="4" summary="ask action"/>
++ </enum>
++ </interface>
++
++ <interface name="wl_shell" version="1">
++ <description summary="create desktop-style surfaces">
++ This interface is implemented by servers that provide
++ desktop-style user interfaces.
++
++ It allows clients to associate a wl_shell_surface with
++ a basic surface.
++
++ Note! This protocol is deprecated and not intended for production use.
++ For desktop-style user interfaces, use xdg_shell. Compositors and clients
++ should not implement this interface.
++ </description>
++
++ <enum name="error">
++ <entry name="role" value="0" summary="given wl_surface has another role"/>
++ </enum>
++
++ <request name="get_shell_surface">
++ <description summary="create a shell surface from a surface">
++ Create a shell surface for an existing surface. This gives
++ the wl_surface the role of a shell surface. If the wl_surface
++ already has another role, it raises a protocol error.
++
++ Only one shell surface can be associated with a given surface.
++ </description>
++ <arg name="id" type="new_id" interface="wl_shell_surface" summary="shell surface to create"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="surface to be given the shell surface role"/>
++ </request>
++ </interface>
++
++ <interface name="wl_shell_surface" version="1">
++ <description summary="desktop-style metadata interface">
++ An interface that may be implemented by a wl_surface, for
++ implementations that provide a desktop-style user interface.
++
++ It provides requests to treat surfaces like toplevel, fullscreen
++ or popup windows, move, resize or maximize them, associate
++ metadata like title and class, etc.
++
++ On the server side the object is automatically destroyed when
++ the related wl_surface is destroyed. On the client side,
++ wl_shell_surface_destroy() must be called before destroying
++ the wl_surface object.
++ </description>
++
++ <request name="pong">
++ <description summary="respond to a ping event">
++ A client must respond to a ping event with a pong request or
++ the client may be deemed unresponsive.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the ping event"/>
++ </request>
++
++ <request name="move">
++ <description summary="start an interactive move">
++ Start a pointer-driven move of the surface.
++
++ This request must be used in response to a button press event.
++ The server may ignore move requests depending on the state of
++ the surface (e.g. fullscreen or maximized).
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="seat whose pointer is used"/>
++ <arg name="serial" type="uint" summary="serial number of the implicit grab on the pointer"/>
++ </request>
++
++ <enum name="resize" bitfield="true">
++ <description summary="edge values for resizing">
++ These values are used to indicate which edge of a surface
++ is being dragged in a resize operation. The server may
++ use this information to adapt its behavior, e.g. choose
++ an appropriate cursor image.
++ </description>
++ <entry name="none" value="0" summary="no edge"/>
++ <entry name="top" value="1" summary="top edge"/>
++ <entry name="bottom" value="2" summary="bottom edge"/>
++ <entry name="left" value="4" summary="left edge"/>
++ <entry name="top_left" value="5" summary="top and left edges"/>
++ <entry name="bottom_left" value="6" summary="bottom and left edges"/>
++ <entry name="right" value="8" summary="right edge"/>
++ <entry name="top_right" value="9" summary="top and right edges"/>
++ <entry name="bottom_right" value="10" summary="bottom and right edges"/>
++ </enum>
++
++ <request name="resize">
++ <description summary="start an interactive resize">
++ Start a pointer-driven resizing of the surface.
++
++ This request must be used in response to a button press event.
++ The server may ignore resize requests depending on the state of
++ the surface (e.g. fullscreen or maximized).
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="seat whose pointer is used"/>
++ <arg name="serial" type="uint" summary="serial number of the implicit grab on the pointer"/>
++ <arg name="edges" type="uint" enum="resize" summary="which edge or corner is being dragged"/>
++ </request>
++
++ <request name="set_toplevel">
++ <description summary="make the surface a toplevel surface">
++ Map the surface as a toplevel surface.
++
++ A toplevel surface is not fullscreen, maximized or transient.
++ </description>
++ </request>
++
++ <enum name="transient" bitfield="true">
++ <description summary="details of transient behaviour">
++ These flags specify details of the expected behaviour
++ of transient surfaces. Used in the set_transient request.
++ </description>
++ <entry name="inactive" value="0x1" summary="do not set keyboard focus"/>
++ </enum>
++
++ <request name="set_transient">
++ <description summary="make the surface a transient surface">
++ Map the surface relative to an existing surface.
++
++ The x and y arguments specify the location of the upper left
++ corner of the surface relative to the upper left corner of the
++ parent surface, in surface-local coordinates.
++
++ The flags argument controls details of the transient behaviour.
++ </description>
++ <arg name="parent" type="object" interface="wl_surface" summary="parent surface"/>
++ <arg name="x" type="int" summary="surface-local x coordinate"/>
++ <arg name="y" type="int" summary="surface-local y coordinate"/>
++ <arg name="flags" type="uint" enum="transient" summary="transient surface behavior"/>
++ </request>
++
++ <enum name="fullscreen_method">
++ <description summary="different method to set the surface fullscreen">
++ Hints to indicate to the compositor how to deal with a conflict
++ between the dimensions of the surface and the dimensions of the
++ output. The compositor is free to ignore this parameter.
++ </description>
++ <entry name="default" value="0" summary="no preference, apply default policy"/>
++ <entry name="scale" value="1" summary="scale, preserve the surface's aspect ratio and center on output"/>
++ <entry name="driver" value="2" summary="switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch"/>
++ <entry name="fill" value="3" summary="no upscaling, center on output and add black borders to compensate size mismatch"/>
++ </enum>
++
++ <request name="set_fullscreen">
++ <description summary="make the surface a fullscreen surface">
++ Map the surface as a fullscreen surface.
++
++ If an output parameter is given then the surface will be made
++ fullscreen on that output. If the client does not specify the
++ output then the compositor will apply its policy - usually
++ choosing the output on which the surface has the biggest surface
++ area.
++
++ The client may specify a method to resolve a size conflict
++ between the output size and the surface size - this is provided
++ through the method parameter.
++
++ The framerate parameter is used only when the method is set
++ to "driver", to indicate the preferred framerate. A value of 0
++ indicates that the client does not care about framerate. The
++ framerate is specified in mHz, that is framerate of 60000 is 60Hz.
++
++ A method of "scale" or "driver" implies a scaling operation of
++ the surface, either via a direct scaling operation or a change of
++ the output mode. This will override any kind of output scaling, so
++ that mapping a surface with a buffer size equal to the mode can
++ fill the screen independent of buffer_scale.
++
++ A method of "fill" means we don't scale up the buffer, however
++ any output scale is applied. This means that you may run into
++ an edge case where the application maps a buffer with the same
++ size of the output mode but buffer_scale 1 (thus making a
++ surface larger than the output). In this case it is allowed to
++ downscale the results to fit the screen.
++
++ The compositor must reply to this request with a configure event
++ with the dimensions for the output on which the surface will
++ be made fullscreen.
++ </description>
++ <arg name="method" type="uint" enum="fullscreen_method" summary="method for resolving size conflict"/>
++ <arg name="framerate" type="uint" summary="framerate in mHz"/>
++ <arg name="output" type="object" interface="wl_output" allow-null="true"
++ summary="output on which the surface is to be fullscreen"/>
++ </request>
++
++ <request name="set_popup">
++ <description summary="make the surface a popup surface">
++ Map the surface as a popup.
++
++ A popup surface is a transient surface with an added pointer
++ grab.
++
++ An existing implicit grab will be changed to owner-events mode,
++ and the popup grab will continue after the implicit grab ends
++ (i.e. releasing the mouse button does not cause the popup to
++ be unmapped).
++
++ The popup grab continues until the window is destroyed or a
++ mouse button is pressed in any other client's window. A click
++ in any of the client's surfaces is reported as normal, however,
++ clicks in other clients' surfaces will be discarded and trigger
++ the callback.
++
++ The x and y arguments specify the location of the upper left
++ corner of the surface relative to the upper left corner of the
++ parent surface, in surface-local coordinates.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="seat whose pointer is used"/>
++ <arg name="serial" type="uint" summary="serial number of the implicit grab on the pointer"/>
++ <arg name="parent" type="object" interface="wl_surface" summary="parent surface"/>
++ <arg name="x" type="int" summary="surface-local x coordinate"/>
++ <arg name="y" type="int" summary="surface-local y coordinate"/>
++ <arg name="flags" type="uint" enum="transient" summary="transient surface behavior"/>
++ </request>
++
++ <request name="set_maximized">
++ <description summary="make the surface a maximized surface">
++ Map the surface as a maximized surface.
++
++ If an output parameter is given then the surface will be
++ maximized on that output. If the client does not specify the
++ output then the compositor will apply its policy - usually
++ choosing the output on which the surface has the biggest surface
++ area.
++
++ The compositor will reply with a configure event telling
++ the expected new surface size. The operation is completed
++ on the next buffer attach to this surface.
++
++ A maximized surface typically fills the entire output it is
++ bound to, except for desktop elements such as panels. This is
++ the main difference between a maximized shell surface and a
++ fullscreen shell surface.
++
++ The details depend on the compositor implementation.
++ </description>
++ <arg name="output" type="object" interface="wl_output" allow-null="true"
++ summary="output on which the surface is to be maximized"/>
++ </request>
++
++ <request name="set_title">
++ <description summary="set surface title">
++ Set a short title for the surface.
++
++ This string may be used to identify the surface in a task bar,
++ window list, or other user interface elements provided by the
++ compositor.
++
++ The string must be encoded in UTF-8.
++ </description>
++ <arg name="title" type="string" summary="surface title"/>
++ </request>
++
++ <request name="set_class">
++ <description summary="set surface class">
++ Set a class for the surface.
++
++ The surface class identifies the general class of applications
++ to which the surface belongs. A common convention is to use the
++ file name (or the full path if it is a non-standard location) of
++ the application's .desktop file as the class.
++ </description>
++ <arg name="class_" type="string" summary="surface class"/>
++ </request>
++
++ <event name="ping">
++ <description summary="ping client">
++ Ping a client to check if it is receiving events and sending
++ requests. A client is expected to reply with a pong request.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the ping"/>
++ </event>
++
++ <event name="configure">
++ <description summary="suggest resize">
++ The configure event asks the client to resize its surface.
++
++ The size is a hint, in the sense that the client is free to
++ ignore it if it doesn't resize, pick a smaller size (to
++ satisfy aspect ratio or resize in steps of NxM pixels).
++
++ The edges parameter provides a hint about how the surface
++ was resized. The client may use this information to decide
++ how to adjust its content to the new size (e.g. a scrolling
++ area might adjust its content position to leave the viewable
++ content unmoved).
++
++ The client is free to dismiss all but the last configure
++ event it received.
++
++ The width and height arguments specify the size of the window
++ in surface-local coordinates.
++ </description>
++ <arg name="edges" type="uint" enum="resize" summary="how the surface was resized"/>
++ <arg name="width" type="int" summary="new width of the surface"/>
++ <arg name="height" type="int" summary="new height of the surface"/>
++ </event>
++
++ <event name="popup_done">
++ <description summary="popup interaction is done">
++ The popup_done event is sent out when a popup grab is broken,
++ that is, when the user clicks a surface that doesn't belong
++ to the client owning the popup surface.
++ </description>
++ </event>
++ </interface>
++
++ <interface name="wl_surface" version="5">
++ <description summary="an onscreen surface">
++ A surface is a rectangular area that may be displayed on zero
++ or more outputs, and shown any number of times at the compositor's
++ discretion. They can present wl_buffers, receive user input, and
++ define a local coordinate system.
++
++ The size of a surface (and relative positions on it) is described
++ in surface-local coordinates, which may differ from the buffer
++ coordinates of the pixel content, in case a buffer_transform
++ or a buffer_scale is used.
++
++ A surface without a "role" is fairly useless: a compositor does
++ not know where, when or how to present it. The role is the
++ purpose of a wl_surface. Examples of roles are a cursor for a
++ pointer (as set by wl_pointer.set_cursor), a drag icon
++ (wl_data_device.start_drag), a sub-surface
++ (wl_subcompositor.get_subsurface), and a window as defined by a
++ shell protocol (e.g. wl_shell.get_shell_surface).
++
++ A surface can have only one role at a time. Initially a
++ wl_surface does not have a role. Once a wl_surface is given a
++ role, it is set permanently for the whole lifetime of the
++ wl_surface object. Giving the current role again is allowed,
++ unless explicitly forbidden by the relevant interface
++ specification.
++
++ Surface roles are given by requests in other interfaces such as
++ wl_pointer.set_cursor. The request should explicitly mention
++ that this request gives a role to a wl_surface. Often, this
++ request also creates a new protocol object that represents the
++ role and adds additional functionality to wl_surface. When a
++ client wants to destroy a wl_surface, they must destroy this 'role
++ object' before the wl_surface.
++
++ Destroying the role object does not remove the role from the
++ wl_surface, but it may stop the wl_surface from "playing the role".
++ For instance, if a wl_subsurface object is destroyed, the wl_surface
++ it was created for will be unmapped and forget its position and
++ z-order. It is allowed to create a wl_subsurface for the same
++ wl_surface again, but it is not allowed to use the wl_surface as
++ a cursor (cursor is a different role than sub-surface, and role
++ switching is not allowed).
++ </description>
++
++ <enum name="error">
++ <description summary="wl_surface error values">
++ These errors can be emitted in response to wl_surface requests.
++ </description>
++ <entry name="invalid_scale" value="0" summary="buffer scale value is invalid"/>
++ <entry name="invalid_transform" value="1" summary="buffer transform value is invalid"/>
++ <entry name="invalid_size" value="2" summary="buffer size is invalid"/>
++ <entry name="invalid_offset" value="3" summary="buffer offset is invalid"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="delete surface">
++ Deletes the surface and invalidates its object ID.
++ </description>
++ </request>
++
++ <request name="attach">
++ <description summary="set the surface contents">
++ Set a buffer as the content of this surface.
++
++ The new size of the surface is calculated based on the buffer
++ size transformed by the inverse buffer_transform and the
++ inverse buffer_scale. This means that at commit time the supplied
++ buffer size must be an integer multiple of the buffer_scale. If
++ that's not the case, an invalid_size error is sent.
++
++ The x and y arguments specify the location of the new pending
++ buffer's upper left corner, relative to the current buffer's upper
++ left corner, in surface-local coordinates. In other words, the
++ x and y, combined with the new surface size define in which
++ directions the surface's size changes. Setting anything other than 0
++ as x and y arguments is discouraged, and should instead be replaced
++ with using the separate wl_surface.offset request.
++
++ When the bound wl_surface version is 5 or higher, passing any
++ non-zero x or y is a protocol violation, and will result in an
++ 'invalid_offset' error being raised. To achieve equivalent semantics,
++ use wl_surface.offset.
++
++ Surface contents are double-buffered state, see wl_surface.commit.
++
++ The initial surface contents are void; there is no content.
++ wl_surface.attach assigns the given wl_buffer as the pending
++ wl_buffer. wl_surface.commit makes the pending wl_buffer the new
++ surface contents, and the size of the surface becomes the size
++ calculated from the wl_buffer, as described above. After commit,
++ there is no pending buffer until the next attach.
++
++ Committing a pending wl_buffer allows the compositor to read the
++ pixels in the wl_buffer. The compositor may access the pixels at
++ any time after the wl_surface.commit request. When the compositor
++ will not access the pixels anymore, it will send the
++ wl_buffer.release event. Only after receiving wl_buffer.release,
++ the client may reuse the wl_buffer. A wl_buffer that has been
++ attached and then replaced by another attach instead of committed
++ will not receive a release event, and is not used by the
++ compositor.
++
++ If a pending wl_buffer has been committed to more than one wl_surface,
++ the delivery of wl_buffer.release events becomes undefined. A well
++ behaved client should not rely on wl_buffer.release events in this
++ case. Alternatively, a client could create multiple wl_buffer objects
++ from the same backing storage or use wp_linux_buffer_release.
++
++ Destroying the wl_buffer after wl_buffer.release does not change
++ the surface contents. Destroying the wl_buffer before wl_buffer.release
++ is allowed as long as the underlying buffer storage isn't re-used (this
++ can happen e.g. on client process termination). However, if the client
++ destroys the wl_buffer before receiving the wl_buffer.release event and
++ mutates the underlying buffer storage, the surface contents become
++ undefined immediately.
++
++ If wl_surface.attach is sent with a NULL wl_buffer, the
++ following wl_surface.commit will remove the surface content.
++ </description>
++ <arg name="buffer" type="object" interface="wl_buffer" allow-null="true"
++ summary="buffer of surface contents"/>
++ <arg name="x" type="int" summary="surface-local x coordinate"/>
++ <arg name="y" type="int" summary="surface-local y coordinate"/>
++ </request>
++
++ <request name="damage">
++ <description summary="mark part of the surface damaged">
++ This request is used to describe the regions where the pending
++ buffer is different from the current surface contents, and where
++ the surface therefore needs to be repainted. The compositor
++ ignores the parts of the damage that fall outside of the surface.
++
++ Damage is double-buffered state, see wl_surface.commit.
++
++ The damage rectangle is specified in surface-local coordinates,
++ where x and y specify the upper left corner of the damage rectangle.
++
++ The initial value for pending damage is empty: no damage.
++ wl_surface.damage adds pending damage: the new pending damage
++ is the union of old pending damage and the given rectangle.
++
++ wl_surface.commit assigns pending damage as the current damage,
++ and clears pending damage. The server will clear the current
++ damage as it repaints the surface.
++
++ Note! New clients should not use this request. Instead damage can be
++ posted with wl_surface.damage_buffer which uses buffer coordinates
++ instead of surface coordinates.
++ </description>
++ <arg name="x" type="int" summary="surface-local x coordinate"/>
++ <arg name="y" type="int" summary="surface-local y coordinate"/>
++ <arg name="width" type="int" summary="width of damage rectangle"/>
++ <arg name="height" type="int" summary="height of damage rectangle"/>
++ </request>
++
++ <request name="frame">
++ <description summary="request a frame throttling hint">
++ Request a notification when it is a good time to start drawing a new
++ frame, by creating a frame callback. This is useful for throttling
++ redrawing operations, and driving animations.
++
++ When a client is animating on a wl_surface, it can use the 'frame'
++ request to get notified when it is a good time to draw and commit the
++ next frame of animation. If the client commits an update earlier than
++ that, it is likely that some updates will not make it to the display,
++ and the client is wasting resources by drawing too often.
++
++ The frame request will take effect on the next wl_surface.commit.
++ The notification will only be posted for one frame unless
++ requested again. For a wl_surface, the notifications are posted in
++ the order the frame requests were committed.
++
++ The server must send the notifications so that a client
++ will not send excessive updates, while still allowing
++ the highest possible update rate for clients that wait for the reply
++ before drawing again. The server should give some time for the client
++ to draw and commit after sending the frame callback events to let it
++ hit the next output refresh.
++
++ A server should avoid signaling the frame callbacks if the
++ surface is not visible in any way, e.g. the surface is off-screen,
++ or completely obscured by other opaque surfaces.
++
++ The object returned by this request will be destroyed by the
++ compositor after the callback is fired and as such the client must not
++ attempt to use it after that point.
++
++ The callback_data passed in the callback is the current time, in
++ milliseconds, with an undefined base.
++ </description>
++ <arg name="callback" type="new_id" interface="wl_callback" summary="callback object for the frame request"/>
++ </request>
++
++ <request name="set_opaque_region">
++ <description summary="set opaque region">
++ This request sets the region of the surface that contains
++ opaque content.
++
++ The opaque region is an optimization hint for the compositor
++ that lets it optimize the redrawing of content behind opaque
++ regions. Setting an opaque region is not required for correct
++ behaviour, but marking transparent content as opaque will result
++ in repaint artifacts.
++
++ The opaque region is specified in surface-local coordinates.
++
++ The compositor ignores the parts of the opaque region that fall
++ outside of the surface.
++
++ Opaque region is double-buffered state, see wl_surface.commit.
++
++ wl_surface.set_opaque_region changes the pending opaque region.
++ wl_surface.commit copies the pending region to the current region.
++ Otherwise, the pending and current regions are never changed.
++
++ The initial value for an opaque region is empty. Setting the pending
++ opaque region has copy semantics, and the wl_region object can be
++ destroyed immediately. A NULL wl_region causes the pending opaque
++ region to be set to empty.
++ </description>
++ <arg name="region" type="object" interface="wl_region" allow-null="true"
++ summary="opaque region of the surface"/>
++ </request>
++
++ <request name="set_input_region">
++ <description summary="set input region">
++ This request sets the region of the surface that can receive
++ pointer and touch events.
++
++ Input events happening outside of this region will try the next
++ surface in the server surface stack. The compositor ignores the
++ parts of the input region that fall outside of the surface.
++
++ The input region is specified in surface-local coordinates.
++
++ Input region is double-buffered state, see wl_surface.commit.
++
++ wl_surface.set_input_region changes the pending input region.
++ wl_surface.commit copies the pending region to the current region.
++ Otherwise the pending and current regions are never changed,
++ except cursor and icon surfaces are special cases, see
++ wl_pointer.set_cursor and wl_data_device.start_drag.
++
++ The initial value for an input region is infinite. That means the
++ whole surface will accept input. Setting the pending input region
++ has copy semantics, and the wl_region object can be destroyed
++ immediately. A NULL wl_region causes the input region to be set
++ to infinite.
++ </description>
++ <arg name="region" type="object" interface="wl_region" allow-null="true"
++ summary="input region of the surface"/>
++ </request>
++
++ <request name="commit">
++ <description summary="commit pending surface state">
++ Surface state (input, opaque, and damage regions, attached buffers,
++ etc.) is double-buffered. Protocol requests modify the pending state,
++ as opposed to the current state in use by the compositor. A commit
++ request atomically applies all pending state, replacing the current
++ state. After commit, the new pending state is as documented for each
++ related request.
++
++ On commit, a pending wl_buffer is applied first, and all other state
++ second. This means that all coordinates in double-buffered state are
++ relative to the new wl_buffer coming into use, except for
++ wl_surface.attach itself. If there is no pending wl_buffer, the
++ coordinates are relative to the current surface contents.
++
++ All requests that need a commit to become effective are documented
++ to affect double-buffered state.
++
++ Other interfaces may add further double-buffered surface state.
++ </description>
++ </request>
++
++ <event name="enter">
++ <description summary="surface enters an output">
++ This is emitted whenever a surface's creation, movement, or resizing
++ results in some part of it being within the scanout region of an
++ output.
++
++ Note that a surface may be overlapping with zero or more outputs.
++ </description>
++ <arg name="output" type="object" interface="wl_output" summary="output entered by the surface"/>
++ </event>
++
++ <event name="leave">
++ <description summary="surface leaves an output">
++ This is emitted whenever a surface's creation, movement, or resizing
++ results in it no longer having any part of it within the scanout region
++ of an output.
++
++ Clients should not use the number of outputs the surface is on for frame
++ throttling purposes. The surface might be hidden even if no leave event
++ has been sent, and the compositor might expect new surface content
++ updates even if no enter event has been sent. The frame event should be
++ used instead.
++ </description>
++ <arg name="output" type="object" interface="wl_output" summary="output left by the surface"/>
++ </event>
++
++ <!-- Version 2 additions -->
++
++ <request name="set_buffer_transform" since="2">
++ <description summary="sets the buffer transformation">
++ This request sets an optional transformation on how the compositor
++ interprets the contents of the buffer attached to the surface. The
++ accepted values for the transform parameter are the values for
++ wl_output.transform.
++
++ Buffer transform is double-buffered state, see wl_surface.commit.
++
++ A newly created surface has its buffer transformation set to normal.
++
++ wl_surface.set_buffer_transform changes the pending buffer
++ transformation. wl_surface.commit copies the pending buffer
++ transformation to the current one. Otherwise, the pending and current
++ values are never changed.
++
++ The purpose of this request is to allow clients to render content
++ according to the output transform, thus permitting the compositor to
++ use certain optimizations even if the display is rotated. Using
++ hardware overlays and scanning out a client buffer for fullscreen
++ surfaces are examples of such optimizations. Those optimizations are
++ highly dependent on the compositor implementation, so the use of this
++ request should be considered on a case-by-case basis.
++
++ Note that if the transform value includes 90 or 270 degree rotation,
++ the width of the buffer will become the surface height and the height
++ of the buffer will become the surface width.
++
++ If transform is not one of the values from the
++ wl_output.transform enum the invalid_transform protocol error
++ is raised.
++ </description>
++ <arg name="transform" type="int" enum="wl_output.transform"
++ summary="transform for interpreting buffer contents"/>
++ </request>
++
++ <!-- Version 3 additions -->
++
++ <request name="set_buffer_scale" since="3">
++ <description summary="sets the buffer scaling factor">
++ This request sets an optional scaling factor on how the compositor
++ interprets the contents of the buffer attached to the window.
++
++ Buffer scale is double-buffered state, see wl_surface.commit.
++
++ A newly created surface has its buffer scale set to 1.
++
++ wl_surface.set_buffer_scale changes the pending buffer scale.
++ wl_surface.commit copies the pending buffer scale to the current one.
++ Otherwise, the pending and current values are never changed.
++
++ The purpose of this request is to allow clients to supply higher
++ resolution buffer data for use on high resolution outputs. It is
++ intended that you pick the same buffer scale as the scale of the
++ output that the surface is displayed on. This means the compositor
++ can avoid scaling when rendering the surface on that output.
++
++ Note that if the scale is larger than 1, then you have to attach
++ a buffer that is larger (by a factor of scale in each dimension)
++ than the desired surface size.
++
++ If scale is not positive the invalid_scale protocol error is
++ raised.
++ </description>
++ <arg name="scale" type="int"
++ summary="positive scale for interpreting buffer contents"/>
++ </request>
++
++ <!-- Version 4 additions -->
++ <request name="damage_buffer" since="4">
++ <description summary="mark part of the surface damaged using buffer coordinates">
++ This request is used to describe the regions where the pending
++ buffer is different from the current surface contents, and where
++ the surface therefore needs to be repainted. The compositor
++ ignores the parts of the damage that fall outside of the surface.
++
++ Damage is double-buffered state, see wl_surface.commit.
++
++ The damage rectangle is specified in buffer coordinates,
++ where x and y specify the upper left corner of the damage rectangle.
++
++ The initial value for pending damage is empty: no damage.
++ wl_surface.damage_buffer adds pending damage: the new pending
++ damage is the union of old pending damage and the given rectangle.
++
++ wl_surface.commit assigns pending damage as the current damage,
++ and clears pending damage. The server will clear the current
++ damage as it repaints the surface.
++
++ This request differs from wl_surface.damage in only one way - it
++ takes damage in buffer coordinates instead of surface-local
++ coordinates. While this generally is more intuitive than surface
++ coordinates, it is especially desirable when using wp_viewport
++ or when a drawing library (like EGL) is unaware of buffer scale
++ and buffer transform.
++
++ Note: Because buffer transformation changes and damage requests may
++ be interleaved in the protocol stream, it is impossible to determine
++ the actual mapping between surface and buffer damage until
++ wl_surface.commit time. Therefore, compositors wishing to take both
++ kinds of damage into account will have to accumulate damage from the
++ two requests separately and only transform from one to the other
++ after receiving the wl_surface.commit.
++ </description>
++ <arg name="x" type="int" summary="buffer-local x coordinate"/>
++ <arg name="y" type="int" summary="buffer-local y coordinate"/>
++ <arg name="width" type="int" summary="width of damage rectangle"/>
++ <arg name="height" type="int" summary="height of damage rectangle"/>
++ </request>
++
++ <!-- Version 5 additions -->
++
++ <request name="offset" since="5">
++ <description summary="set the surface contents offset">
++ The x and y arguments specify the location of the new pending
++ buffer's upper left corner, relative to the current buffer's upper
++ left corner, in surface-local coordinates. In other words, the
++ x and y, combined with the new surface size define in which
++ directions the surface's size changes.
++
++ Surface location offset is double-buffered state, see
++ wl_surface.commit.
++
++ This request is semantically equivalent to and the replaces the x and y
++ arguments in the wl_surface.attach request in wl_surface versions prior
++ to 5. See wl_surface.attach for details.
++ </description>
++ <arg name="x" type="int" summary="surface-local x coordinate"/>
++ <arg name="y" type="int" summary="surface-local y coordinate"/>
++ </request>
++ </interface>
++
++ <interface name="wl_seat" version="8">
++ <description summary="group of input devices">
++ A seat is a group of keyboards, pointer and touch devices. This
++ object is published as a global during start up, or when such a
++ device is hot plugged. A seat typically has a pointer and
++ maintains a keyboard focus and a pointer focus.
++ </description>
++
++ <enum name="capability" bitfield="true">
++ <description summary="seat capability bitmask">
++ This is a bitmask of capabilities this seat has; if a member is
++ set, then it is present on the seat.
++ </description>
++ <entry name="pointer" value="1" summary="the seat has pointer devices"/>
++ <entry name="keyboard" value="2" summary="the seat has one or more keyboards"/>
++ <entry name="touch" value="4" summary="the seat has touch devices"/>
++ </enum>
++
++ <enum name="error">
++ <description summary="wl_seat error values">
++ These errors can be emitted in response to wl_seat requests.
++ </description>
++ <entry name="missing_capability" value="0"
++ summary="get_pointer, get_keyboard or get_touch called on seat without the matching capability"/>
++ </enum>
++
++ <event name="capabilities">
++ <description summary="seat capabilities changed">
++ This is emitted whenever a seat gains or loses the pointer,
++ keyboard or touch capabilities. The argument is a capability
++ enum containing the complete set of capabilities this seat has.
++
++ When the pointer capability is added, a client may create a
++ wl_pointer object using the wl_seat.get_pointer request. This object
++ will receive pointer events until the capability is removed in the
++ future.
++
++ When the pointer capability is removed, a client should destroy the
++ wl_pointer objects associated with the seat where the capability was
++ removed, using the wl_pointer.release request. No further pointer
++ events will be received on these objects.
++
++ In some compositors, if a seat regains the pointer capability and a
++ client has a previously obtained wl_pointer object of version 4 or
++ less, that object may start sending pointer events again. This
++ behavior is considered a misinterpretation of the intended behavior
++ and must not be relied upon by the client. wl_pointer objects of
++ version 5 or later must not send events if created before the most
++ recent event notifying the client of an added pointer capability.
++
++ The above behavior also applies to wl_keyboard and wl_touch with the
++ keyboard and touch capabilities, respectively.
++ </description>
++ <arg name="capabilities" type="uint" enum="capability" summary="capabilities of the seat"/>
++ </event>
++
++ <request name="get_pointer">
++ <description summary="return pointer object">
++ The ID provided will be initialized to the wl_pointer interface
++ for this seat.
++
++ This request only takes effect if the seat has the pointer
++ capability, or has had the pointer capability in the past.
++ It is a protocol violation to issue this request on a seat that has
++ never had the pointer capability. The missing_capability error will
++ be sent in this case.
++ </description>
++ <arg name="id" type="new_id" interface="wl_pointer" summary="seat pointer"/>
++ </request>
++
++ <request name="get_keyboard">
++ <description summary="return keyboard object">
++ The ID provided will be initialized to the wl_keyboard interface
++ for this seat.
++
++ This request only takes effect if the seat has the keyboard
++ capability, or has had the keyboard capability in the past.
++ It is a protocol violation to issue this request on a seat that has
++ never had the keyboard capability. The missing_capability error will
++ be sent in this case.
++ </description>
++ <arg name="id" type="new_id" interface="wl_keyboard" summary="seat keyboard"/>
++ </request>
++
++ <request name="get_touch">
++ <description summary="return touch object">
++ The ID provided will be initialized to the wl_touch interface
++ for this seat.
++
++ This request only takes effect if the seat has the touch
++ capability, or has had the touch capability in the past.
++ It is a protocol violation to issue this request on a seat that has
++ never had the touch capability. The missing_capability error will
++ be sent in this case.
++ </description>
++ <arg name="id" type="new_id" interface="wl_touch" summary="seat touch interface"/>
++ </request>
++
++ <!-- Version 2 additions -->
++
++ <event name="name" since="2">
++ <description summary="unique identifier for this seat">
++ In a multi-seat configuration the seat name can be used by clients to
++ help identify which physical devices the seat represents.
++
++ The seat name is a UTF-8 string with no convention defined for its
++ contents. Each name is unique among all wl_seat globals. The name is
++ only guaranteed to be unique for the current compositor instance.
++
++ The same seat names are used for all clients. Thus, the name can be
++ shared across processes to refer to a specific wl_seat global.
++
++ The name event is sent after binding to the seat global. This event is
++ only sent once per seat object, and the name does not change over the
++ lifetime of the wl_seat global.
++
++ Compositors may re-use the same seat name if the wl_seat global is
++ destroyed and re-created later.
++ </description>
++ <arg name="name" type="string" summary="seat identifier"/>
++ </event>
++
++ <!-- Version 5 additions -->
++
++ <request name="release" type="destructor" since="5">
++ <description summary="release the seat object">
++ Using this request a client can tell the server that it is not going to
++ use the seat object anymore.
++ </description>
++ </request>
++
++ </interface>
++
++ <interface name="wl_pointer" version="8">
++ <description summary="pointer input device">
++ The wl_pointer interface represents one or more input devices,
++ such as mice, which control the pointer location and pointer_focus
++ of a seat.
++
++ The wl_pointer interface generates motion, enter and leave
++ events for the surfaces that the pointer is located over,
++ and button and axis events for button presses, button releases
++ and scrolling.
++ </description>
++
++ <enum name="error">
++ <entry name="role" value="0" summary="given wl_surface has another role"/>
++ </enum>
++
++ <request name="set_cursor">
++ <description summary="set the pointer surface">
++ Set the pointer surface, i.e., the surface that contains the
++ pointer image (cursor). This request gives the surface the role
++ of a cursor. If the surface already has another role, it raises
++ a protocol error.
++
++ The cursor actually changes only if the pointer
++ focus for this device is one of the requesting client's surfaces
++ or the surface parameter is the current pointer surface. If
++ there was a previous surface set with this request it is
++ replaced. If surface is NULL, the pointer image is hidden.
++
++ The parameters hotspot_x and hotspot_y define the position of
++ the pointer surface relative to the pointer location. Its
++ top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
++ where (x, y) are the coordinates of the pointer location, in
++ surface-local coordinates.
++
++ On surface.attach requests to the pointer surface, hotspot_x
++ and hotspot_y are decremented by the x and y parameters
++ passed to the request. Attach must be confirmed by
++ wl_surface.commit as usual.
++
++ The hotspot can also be updated by passing the currently set
++ pointer surface to this request with new values for hotspot_x
++ and hotspot_y.
++
++ The current and pending input regions of the wl_surface are
++ cleared, and wl_surface.set_input_region is ignored until the
++ wl_surface is no longer used as the cursor. When the use as a
++ cursor ends, the current and pending input regions become
++ undefined, and the wl_surface is unmapped.
++
++ The serial parameter must match the latest wl_pointer.enter
++ serial number sent to the client. Otherwise the request will be
++ ignored.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the enter event"/>
++ <arg name="surface" type="object" interface="wl_surface" allow-null="true"
++ summary="pointer surface"/>
++ <arg name="hotspot_x" type="int" summary="surface-local x coordinate"/>
++ <arg name="hotspot_y" type="int" summary="surface-local y coordinate"/>
++ </request>
++
++ <event name="enter">
++ <description summary="enter event">
++ Notification that this seat's pointer is focused on a certain
++ surface.
++
++ When a seat's focus enters a surface, the pointer image
++ is undefined and a client should respond to this event by setting
++ an appropriate pointer image with the set_cursor request.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the enter event"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="surface entered by the pointer"/>
++ <arg name="surface_x" type="fixed" summary="surface-local x coordinate"/>
++ <arg name="surface_y" type="fixed" summary="surface-local y coordinate"/>
++ </event>
++
++ <event name="leave">
++ <description summary="leave event">
++ Notification that this seat's pointer is no longer focused on
++ a certain surface.
++
++ The leave notification is sent before the enter notification
++ for the new focus.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the leave event"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="surface left by the pointer"/>
++ </event>
++
++ <event name="motion">
++ <description summary="pointer motion event">
++ Notification of pointer location change. The arguments
++ surface_x and surface_y are the location relative to the
++ focused surface.
++ </description>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="surface_x" type="fixed" summary="surface-local x coordinate"/>
++ <arg name="surface_y" type="fixed" summary="surface-local y coordinate"/>
++ </event>
++
++ <enum name="button_state">
++ <description summary="physical button state">
++ Describes the physical state of a button that produced the button
++ event.
++ </description>
++ <entry name="released" value="0" summary="the button is not pressed"/>
++ <entry name="pressed" value="1" summary="the button is pressed"/>
++ </enum>
++
++ <event name="button">
++ <description summary="pointer button event">
++ Mouse button click and release notifications.
++
++ The location of the click is given by the last motion or
++ enter event.
++ The time argument is a timestamp with millisecond
++ granularity, with an undefined base.
++
++ The button is a button code as defined in the Linux kernel's
++ linux/input-event-codes.h header file, e.g. BTN_LEFT.
++
++ Any 16-bit button code value is reserved for future additions to the
++ kernel's event code list. All other button codes above 0xFFFF are
++ currently undefined but may be used in future versions of this
++ protocol.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the button event"/>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="button" type="uint" summary="button that produced the event"/>
++ <arg name="state" type="uint" enum="button_state" summary="physical state of the button"/>
++ </event>
++
++ <enum name="axis">
++ <description summary="axis types">
++ Describes the axis types of scroll events.
++ </description>
++ <entry name="vertical_scroll" value="0" summary="vertical axis"/>
++ <entry name="horizontal_scroll" value="1" summary="horizontal axis"/>
++ </enum>
++
++ <event name="axis">
++ <description summary="axis event">
++ Scroll and other axis notifications.
++
++ For scroll events (vertical and horizontal scroll axes), the
++ value parameter is the length of a vector along the specified
++ axis in a coordinate space identical to those of motion events,
++ representing a relative movement along the specified axis.
++
++ For devices that support movements non-parallel to axes multiple
++ axis events will be emitted.
++
++ When applicable, for example for touch pads, the server can
++ choose to emit scroll events where the motion vector is
++ equivalent to a motion event vector.
++
++ When applicable, a client can transform its content relative to the
++ scroll distance.
++ </description>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="axis" type="uint" enum="axis" summary="axis type"/>
++ <arg name="value" type="fixed" summary="length of vector in surface-local coordinate space"/>
++ </event>
++
++ <!-- Version 3 additions -->
++
++ <request name="release" type="destructor" since="3">
++ <description summary="release the pointer object">
++ Using this request a client can tell the server that it is not going to
++ use the pointer object anymore.
++
++ This request destroys the pointer proxy object, so clients must not call
++ wl_pointer_destroy() after using this request.
++ </description>
++ </request>
++
++ <!-- Version 5 additions -->
++
++ <event name="frame" since="5">
++ <description summary="end of a pointer event sequence">
++ Indicates the end of a set of events that logically belong together.
++ A client is expected to accumulate the data in all events within the
++ frame before proceeding.
++
++ All wl_pointer events before a wl_pointer.frame event belong
++ logically together. For example, in a diagonal scroll motion the
++ compositor will send an optional wl_pointer.axis_source event, two
++ wl_pointer.axis events (horizontal and vertical) and finally a
++ wl_pointer.frame event. The client may use this information to
++ calculate a diagonal vector for scrolling.
++
++ When multiple wl_pointer.axis events occur within the same frame,
++ the motion vector is the combined motion of all events.
++ When a wl_pointer.axis and a wl_pointer.axis_stop event occur within
++ the same frame, this indicates that axis movement in one axis has
++ stopped but continues in the other axis.
++ When multiple wl_pointer.axis_stop events occur within the same
++ frame, this indicates that these axes stopped in the same instance.
++
++ A wl_pointer.frame event is sent for every logical event group,
++ even if the group only contains a single wl_pointer event.
++ Specifically, a client may get a sequence: motion, frame, button,
++ frame, axis, frame, axis_stop, frame.
++
++ The wl_pointer.enter and wl_pointer.leave events are logical events
++ generated by the compositor and not the hardware. These events are
++ also grouped by a wl_pointer.frame. When a pointer moves from one
++ surface to another, a compositor should group the
++ wl_pointer.leave event within the same wl_pointer.frame.
++ However, a client must not rely on wl_pointer.leave and
++ wl_pointer.enter being in the same wl_pointer.frame.
++ Compositor-specific policies may require the wl_pointer.leave and
++ wl_pointer.enter event being split across multiple wl_pointer.frame
++ groups.
++ </description>
++ </event>
++
++ <enum name="axis_source">
++ <description summary="axis source types">
++ Describes the source types for axis events. This indicates to the
++ client how an axis event was physically generated; a client may
++ adjust the user interface accordingly. For example, scroll events
++ from a "finger" source may be in a smooth coordinate space with
++ kinetic scrolling whereas a "wheel" source may be in discrete steps
++ of a number of lines.
++
++ The "continuous" axis source is a device generating events in a
++ continuous coordinate space, but using something other than a
++ finger. One example for this source is button-based scrolling where
++ the vertical motion of a device is converted to scroll events while
++ a button is held down.
++
++ The "wheel tilt" axis source indicates that the actual device is a
++ wheel but the scroll event is not caused by a rotation but a
++ (usually sideways) tilt of the wheel.
++ </description>
++ <entry name="wheel" value="0" summary="a physical wheel rotation" />
++ <entry name="finger" value="1" summary="finger on a touch surface" />
++ <entry name="continuous" value="2" summary="continuous coordinate space"/>
++ <entry name="wheel_tilt" value="3" summary="a physical wheel tilt" since="6"/>
++ </enum>
++
++ <event name="axis_source" since="5">
++ <description summary="axis source event">
++ Source information for scroll and other axes.
++
++ This event does not occur on its own. It is sent before a
++ wl_pointer.frame event and carries the source information for
++ all events within that frame.
++
++ The source specifies how this event was generated. If the source is
++ wl_pointer.axis_source.finger, a wl_pointer.axis_stop event will be
++ sent when the user lifts the finger off the device.
++
++ If the source is wl_pointer.axis_source.wheel,
++ wl_pointer.axis_source.wheel_tilt or
++ wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event may
++ or may not be sent. Whether a compositor sends an axis_stop event
++ for these sources is hardware-specific and implementation-dependent;
++ clients must not rely on receiving an axis_stop event for these
++ scroll sources and should treat scroll sequences from these scroll
++ sources as unterminated by default.
++
++ This event is optional. If the source is unknown for a particular
++ axis event sequence, no event is sent.
++ Only one wl_pointer.axis_source event is permitted per frame.
++
++ The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
++ not guaranteed.
++ </description>
++ <arg name="axis_source" type="uint" enum="axis_source" summary="source of the axis event"/>
++ </event>
++
++ <event name="axis_stop" since="5">
++ <description summary="axis stop event">
++ Stop notification for scroll and other axes.
++
++ For some wl_pointer.axis_source types, a wl_pointer.axis_stop event
++ is sent to notify a client that the axis sequence has terminated.
++ This enables the client to implement kinetic scrolling.
++ See the wl_pointer.axis_source documentation for information on when
++ this event may be generated.
++
++ Any wl_pointer.axis events with the same axis_source after this
++ event should be considered as the start of a new axis motion.
++
++ The timestamp is to be interpreted identical to the timestamp in the
++ wl_pointer.axis event. The timestamp value may be the same as a
++ preceding wl_pointer.axis event.
++ </description>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="axis" type="uint" enum="axis" summary="the axis stopped with this event"/>
++ </event>
++
++ <event name="axis_discrete" since="5">
++ <description summary="axis click event">
++ Discrete step information for scroll and other axes.
++
++ This event carries the axis value of the wl_pointer.axis event in
++ discrete steps (e.g. mouse wheel clicks).
++
++ This event is deprecated with wl_pointer version 8 - this event is not
++ sent to clients supporting version 8 or later.
++
++ This event does not occur on its own, it is coupled with a
++ wl_pointer.axis event that represents this axis value on a
++ continuous scale. The protocol guarantees that each axis_discrete
++ event is always followed by exactly one axis event with the same
++ axis number within the same wl_pointer.frame. Note that the protocol
++ allows for other events to occur between the axis_discrete and
++ its coupled axis event, including other axis_discrete or axis
++ events. A wl_pointer.frame must not contain more than one axis_discrete
++ event per axis type.
++
++ This event is optional; continuous scrolling devices
++ like two-finger scrolling on touchpads do not have discrete
++ steps and do not generate this event.
++
++ The discrete value carries the directional information. e.g. a value
++ of -2 is two steps towards the negative direction of this axis.
++
++ The axis number is identical to the axis number in the associated
++ axis event.
++
++ The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
++ not guaranteed.
++ </description>
++ <arg name="axis" type="uint" enum="axis" summary="axis type"/>
++ <arg name="discrete" type="int" summary="number of steps"/>
++ </event>
++
++ <event name="axis_value120" since="8">
++ <description summary="axis high-resolution scroll event">
++ Discrete high-resolution scroll information.
++
++ This event carries high-resolution wheel scroll information,
++ with each multiple of 120 representing one logical scroll step
++ (a wheel detent). For example, an axis_value120 of 30 is one quarter of
++ a logical scroll step in the positive direction, a value120 of
++ -240 are two logical scroll steps in the negative direction within the
++ same hardware event.
++ Clients that rely on discrete scrolling should accumulate the
++ value120 to multiples of 120 before processing the event.
++
++ The value120 must not be zero.
++
++ This event replaces the wl_pointer.axis_discrete event in clients
++ supporting wl_pointer version 8 or later.
++
++ Where a wl_pointer.axis_source event occurs in the same
++ wl_pointer.frame, the axis source applies to this event.
++
++ The order of wl_pointer.axis_value120 and wl_pointer.axis_source is
++ not guaranteed.
++ </description>
++ <arg name="axis" type="uint" enum="axis" summary="axis type"/>
++ <arg name="value120" type="int" summary="scroll distance as fraction of 120"/>
++ </event>
++ </interface>
++
++ <interface name="wl_keyboard" version="8">
++ <description summary="keyboard input device">
++ The wl_keyboard interface represents one or more keyboards
++ associated with a seat.
++ </description>
++
++ <enum name="keymap_format">
++ <description summary="keyboard mapping format">
++ This specifies the format of the keymap provided to the
++ client with the wl_keyboard.keymap event.
++ </description>
++ <entry name="no_keymap" value="0"
++ summary="no keymap; client must understand how to interpret the raw keycode"/>
++ <entry name="xkb_v1" value="1"
++ summary="libxkbcommon compatible, null-terminated string; to determine the xkb keycode, clients must add 8 to the key event keycode"/>
++ </enum>
++
++ <event name="keymap">
++ <description summary="keyboard mapping">
++ This event provides a file descriptor to the client which can be
++ memory-mapped in read-only mode to provide a keyboard mapping
++ description.
++
++ From version 7 onwards, the fd must be mapped with MAP_PRIVATE by
++ the recipient, as MAP_SHARED may fail.
++ </description>
++ <arg name="format" type="uint" enum="keymap_format" summary="keymap format"/>
++ <arg name="fd" type="fd" summary="keymap file descriptor"/>
++ <arg name="size" type="uint" summary="keymap size, in bytes"/>
++ </event>
++
++ <event name="enter">
++ <description summary="enter event">
++ Notification that this seat's keyboard focus is on a certain
++ surface.
++
++ The compositor must send the wl_keyboard.modifiers event after this
++ event.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the enter event"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="surface gaining keyboard focus"/>
++ <arg name="keys" type="array" summary="the currently pressed keys"/>
++ </event>
++
++ <event name="leave">
++ <description summary="leave event">
++ Notification that this seat's keyboard focus is no longer on
++ a certain surface.
++
++ The leave notification is sent before the enter notification
++ for the new focus.
++
++ After this event client must assume that all keys, including modifiers,
++ are lifted and also it must stop key repeating if there's some going on.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the leave event"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="surface that lost keyboard focus"/>
++ </event>
++
++ <enum name="key_state">
++ <description summary="physical key state">
++ Describes the physical state of a key that produced the key event.
++ </description>
++ <entry name="released" value="0" summary="key is not pressed"/>
++ <entry name="pressed" value="1" summary="key is pressed"/>
++ </enum>
++
++ <event name="key">
++ <description summary="key event">
++ A key was pressed or released.
++ The time argument is a timestamp with millisecond
++ granularity, with an undefined base.
++
++ The key is a platform-specific key code that can be interpreted
++ by feeding it to the keyboard mapping (see the keymap event).
++
++ If this event produces a change in modifiers, then the resulting
++ wl_keyboard.modifiers event must be sent after this event.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the key event"/>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="key" type="uint" summary="key that produced the event"/>
++ <arg name="state" type="uint" enum="key_state" summary="physical state of the key"/>
++ </event>
++
++ <event name="modifiers">
++ <description summary="modifier and group state">
++ Notifies clients that the modifier and/or group state has
++ changed, and it should update its local state.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the modifiers event"/>
++ <arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
++ <arg name="mods_latched" type="uint" summary="latched modifiers"/>
++ <arg name="mods_locked" type="uint" summary="locked modifiers"/>
++ <arg name="group" type="uint" summary="keyboard layout"/>
++ </event>
++
++ <!-- Version 3 additions -->
++
++ <request name="release" type="destructor" since="3">
++ <description summary="release the keyboard object"/>
++ </request>
++
++ <!-- Version 4 additions -->
++
++ <event name="repeat_info" since="4">
++ <description summary="repeat rate and delay">
++ Informs the client about the keyboard's repeat rate and delay.
++
++ This event is sent as soon as the wl_keyboard object has been created,
++ and is guaranteed to be received by the client before any key press
++ event.
++
++ Negative values for either rate or delay are illegal. A rate of zero
++ will disable any repeating (regardless of the value of delay).
++
++ This event can be sent later on as well with a new value if necessary,
++ so clients should continue listening for the event past the creation
++ of wl_keyboard.
++ </description>
++ <arg name="rate" type="int"
++ summary="the rate of repeating keys in characters per second"/>
++ <arg name="delay" type="int"
++ summary="delay in milliseconds since key down until repeating starts"/>
++ </event>
++ </interface>
++
++ <interface name="wl_touch" version="8">
++ <description summary="touchscreen input device">
++ The wl_touch interface represents a touchscreen
++ associated with a seat.
++
++ Touch interactions can consist of one or more contacts.
++ For each contact, a series of events is generated, starting
++ with a down event, followed by zero or more motion events,
++ and ending with an up event. Events relating to the same
++ contact point can be identified by the ID of the sequence.
++ </description>
++
++ <event name="down">
++ <description summary="touch down event and beginning of a touch sequence">
++ A new touch point has appeared on the surface. This touch point is
++ assigned a unique ID. Future events from this touch point reference
++ this ID. The ID ceases to be valid after a touch up event and may be
++ reused in the future.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the touch down event"/>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="surface touched"/>
++ <arg name="id" type="int" summary="the unique ID of this touch point"/>
++ <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++ <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++ </event>
++
++ <event name="up">
++ <description summary="end of a touch event sequence">
++ The touch point has disappeared. No further events will be sent for
++ this touch point and the touch point's ID is released and may be
++ reused in a future touch down event.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the touch up event"/>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="id" type="int" summary="the unique ID of this touch point"/>
++ </event>
++
++ <event name="motion">
++ <description summary="update of touch point coordinates">
++ A touch point has changed coordinates.
++ </description>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="id" type="int" summary="the unique ID of this touch point"/>
++ <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++ <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++ </event>
++
++ <event name="frame">
++ <description summary="end of touch frame event">
++ Indicates the end of a set of events that logically belong together.
++ A client is expected to accumulate the data in all events within the
++ frame before proceeding.
++
++ A wl_touch.frame terminates at least one event but otherwise no
++ guarantee is provided about the set of events within a frame. A client
++ must assume that any state not updated in a frame is unchanged from the
++ previously known state.
++ </description>
++ </event>
++
++ <event name="cancel">
++ <description summary="touch session cancelled">
++ Sent if the compositor decides the touch stream is a global
++ gesture. No further events are sent to the clients from that
++ particular gesture. Touch cancellation applies to all touch points
++ currently active on this client's surface. The client is
++ responsible for finalizing the touch points, future touch points on
++ this surface may reuse the touch point ID.
++ </description>
++ </event>
++
++ <!-- Version 3 additions -->
++
++ <request name="release" type="destructor" since="3">
++ <description summary="release the touch object"/>
++ </request>
++
++ <!-- Version 6 additions -->
++
++ <event name="shape" since="6">
++ <description summary="update shape of touch point">
++ Sent when a touchpoint has changed its shape.
++
++ This event does not occur on its own. It is sent before a
++ wl_touch.frame event and carries the new shape information for
++ any previously reported, or new touch points of that frame.
++
++ Other events describing the touch point such as wl_touch.down,
++ wl_touch.motion or wl_touch.orientation may be sent within the
++ same wl_touch.frame. A client should treat these events as a single
++ logical touch point update. The order of wl_touch.shape,
++ wl_touch.orientation and wl_touch.motion is not guaranteed.
++ A wl_touch.down event is guaranteed to occur before the first
++ wl_touch.shape event for this touch ID but both events may occur within
++ the same wl_touch.frame.
++
++ A touchpoint shape is approximated by an ellipse through the major and
++ minor axis length. The major axis length describes the longer diameter
++ of the ellipse, while the minor axis length describes the shorter
++ diameter. Major and minor are orthogonal and both are specified in
++ surface-local coordinates. The center of the ellipse is always at the
++ touchpoint location as reported by wl_touch.down or wl_touch.move.
++
++ This event is only sent by the compositor if the touch device supports
++ shape reports. The client has to make reasonable assumptions about the
++ shape if it did not receive this event.
++ </description>
++ <arg name="id" type="int" summary="the unique ID of this touch point"/>
++ <arg name="major" type="fixed" summary="length of the major axis in surface-local coordinates"/>
++ <arg name="minor" type="fixed" summary="length of the minor axis in surface-local coordinates"/>
++ </event>
++
++ <event name="orientation" since="6">
++ <description summary="update orientation of touch point">
++ Sent when a touchpoint has changed its orientation.
++
++ This event does not occur on its own. It is sent before a
++ wl_touch.frame event and carries the new shape information for
++ any previously reported, or new touch points of that frame.
++
++ Other events describing the touch point such as wl_touch.down,
++ wl_touch.motion or wl_touch.shape may be sent within the
++ same wl_touch.frame. A client should treat these events as a single
++ logical touch point update. The order of wl_touch.shape,
++ wl_touch.orientation and wl_touch.motion is not guaranteed.
++ A wl_touch.down event is guaranteed to occur before the first
++ wl_touch.orientation event for this touch ID but both events may occur
++ within the same wl_touch.frame.
++
++ The orientation describes the clockwise angle of a touchpoint's major
++ axis to the positive surface y-axis and is normalized to the -180 to
++ +180 degree range. The granularity of orientation depends on the touch
++ device, some devices only support binary rotation values between 0 and
++ 90 degrees.
++
++ This event is only sent by the compositor if the touch device supports
++ orientation reports.
++ </description>
++ <arg name="id" type="int" summary="the unique ID of this touch point"/>
++ <arg name="orientation" type="fixed" summary="angle between major axis and positive surface y-axis in degrees"/>
++ </event>
++ </interface>
++
++ <interface name="wl_output" version="4">
++ <description summary="compositor output region">
++ An output describes part of the compositor geometry. The
++ compositor works in the 'compositor coordinate system' and an
++ output corresponds to a rectangular area in that space that is
++ actually visible. This typically corresponds to a monitor that
++ displays part of the compositor space. This object is published
++ as global during start up, or when a monitor is hotplugged.
++ </description>
++
++ <enum name="subpixel">
++ <description summary="subpixel geometry information">
++ This enumeration describes how the physical
++ pixels on an output are laid out.
++ </description>
++ <entry name="unknown" value="0" summary="unknown geometry"/>
++ <entry name="none" value="1" summary="no geometry"/>
++ <entry name="horizontal_rgb" value="2" summary="horizontal RGB"/>
++ <entry name="horizontal_bgr" value="3" summary="horizontal BGR"/>
++ <entry name="vertical_rgb" value="4" summary="vertical RGB"/>
++ <entry name="vertical_bgr" value="5" summary="vertical BGR"/>
++ </enum>
++
++ <enum name="transform">
++ <description summary="transform from framebuffer to output">
++ This describes the transform that a compositor will apply to a
++ surface to compensate for the rotation or mirroring of an
++ output device.
++
++ The flipped values correspond to an initial flip around a
++ vertical axis followed by rotation.
++
++ The purpose is mainly to allow clients to render accordingly and
++ tell the compositor, so that for fullscreen surfaces, the
++ compositor will still be able to scan out directly from client
++ surfaces.
++ </description>
++ <entry name="normal" value="0" summary="no transform"/>
++ <entry name="90" value="1" summary="90 degrees counter-clockwise"/>
++ <entry name="180" value="2" summary="180 degrees counter-clockwise"/>
++ <entry name="270" value="3" summary="270 degrees counter-clockwise"/>
++ <entry name="flipped" value="4" summary="180 degree flip around a vertical axis"/>
++ <entry name="flipped_90" value="5" summary="flip and rotate 90 degrees counter-clockwise"/>
++ <entry name="flipped_180" value="6" summary="flip and rotate 180 degrees counter-clockwise"/>
++ <entry name="flipped_270" value="7" summary="flip and rotate 270 degrees counter-clockwise"/>
++ </enum>
++
++ <event name="geometry">
++ <description summary="properties of the output">
++ The geometry event describes geometric properties of the output.
++ The event is sent when binding to the output object and whenever
++ any of the properties change.
++
++ The physical size can be set to zero if it doesn't make sense for this
++ output (e.g. for projectors or virtual outputs).
++
++ The geometry event will be followed by a done event (starting from
++ version 2).
++
++ Note: wl_output only advertises partial information about the output
++ position and identification. Some compositors, for instance those not
++ implementing a desktop-style output layout or those exposing virtual
++ outputs, might fake this information. Instead of using x and y, clients
++ should use xdg_output.logical_position. Instead of using make and model,
++ clients should use name and description.
++ </description>
++ <arg name="x" type="int"
++ summary="x position within the global compositor space"/>
++ <arg name="y" type="int"
++ summary="y position within the global compositor space"/>
++ <arg name="physical_width" type="int"
++ summary="width in millimeters of the output"/>
++ <arg name="physical_height" type="int"
++ summary="height in millimeters of the output"/>
++ <arg name="subpixel" type="int" enum="subpixel"
++ summary="subpixel orientation of the output"/>
++ <arg name="make" type="string"
++ summary="textual description of the manufacturer"/>
++ <arg name="model" type="string"
++ summary="textual description of the model"/>
++ <arg name="transform" type="int" enum="transform"
++ summary="transform that maps framebuffer to output"/>
++ </event>
++
++ <enum name="mode" bitfield="true">
++ <description summary="mode information">
++ These flags describe properties of an output mode.
++ They are used in the flags bitfield of the mode event.
++ </description>
++ <entry name="current" value="0x1"
++ summary="indicates this is the current mode"/>
++ <entry name="preferred" value="0x2"
++ summary="indicates this is the preferred mode"/>
++ </enum>
++
++ <event name="mode">
++ <description summary="advertise available modes for the output">
++ The mode event describes an available mode for the output.
++
++ The event is sent when binding to the output object and there
++ will always be one mode, the current mode. The event is sent
++ again if an output changes mode, for the mode that is now
++ current. In other words, the current mode is always the last
++ mode that was received with the current flag set.
++
++ Non-current modes are deprecated. A compositor can decide to only
++ advertise the current mode and never send other modes. Clients
++ should not rely on non-current modes.
++
++ The size of a mode is given in physical hardware units of
++ the output device. This is not necessarily the same as
++ the output size in the global compositor space. For instance,
++ the output may be scaled, as described in wl_output.scale,
++ or transformed, as described in wl_output.transform. Clients
++ willing to retrieve the output size in the global compositor
++ space should use xdg_output.logical_size instead.
++
++ The vertical refresh rate can be set to zero if it doesn't make
++ sense for this output (e.g. for virtual outputs).
++
++ The mode event will be followed by a done event (starting from
++ version 2).
++
++ Clients should not use the refresh rate to schedule frames. Instead,
++ they should use the wl_surface.frame event or the presentation-time
++ protocol.
++
++ Note: this information is not always meaningful for all outputs. Some
++ compositors, such as those exposing virtual outputs, might fake the
++ refresh rate or the size.
++ </description>
++ <arg name="flags" type="uint" enum="mode" summary="bitfield of mode flags"/>
++ <arg name="width" type="int" summary="width of the mode in hardware units"/>
++ <arg name="height" type="int" summary="height of the mode in hardware units"/>
++ <arg name="refresh" type="int" summary="vertical refresh rate in mHz"/>
++ </event>
++
++ <!-- Version 2 additions -->
++
++ <event name="done" since="2">
++ <description summary="sent all information about output">
++ This event is sent after all other properties have been
++ sent after binding to the output object and after any
++ other property changes done after that. This allows
++ changes to the output properties to be seen as
++ atomic, even if they happen via multiple events.
++ </description>
++ </event>
++
++ <event name="scale" since="2">
++ <description summary="output scaling properties">
++ This event contains scaling geometry information
++ that is not in the geometry event. It may be sent after
++ binding the output object or if the output scale changes
++ later. If it is not sent, the client should assume a
++ scale of 1.
++
++ A scale larger than 1 means that the compositor will
++ automatically scale surface buffers by this amount
++ when rendering. This is used for very high resolution
++ displays where applications rendering at the native
++ resolution would be too small to be legible.
++
++ It is intended that scaling aware clients track the
++ current output of a surface, and if it is on a scaled
++ output it should use wl_surface.set_buffer_scale with
++ the scale of the output. That way the compositor can
++ avoid scaling the surface, and the client can supply
++ a higher detail image.
++
++ The scale event will be followed by a done event.
++ </description>
++ <arg name="factor" type="int" summary="scaling factor of output"/>
++ </event>
++
++ <!-- Version 3 additions -->
++
++ <request name="release" type="destructor" since="3">
++ <description summary="release the output object">
++ Using this request a client can tell the server that it is not going to
++ use the output object anymore.
++ </description>
++ </request>
++
++ <!-- Version 4 additions -->
++
++ <event name="name" since="4">
++ <description summary="name of this output">
++ Many compositors will assign user-friendly names to their outputs, show
++ them to the user, allow the user to refer to an output, etc. The client
++ may wish to know this name as well to offer the user similar behaviors.
++
++ The name is a UTF-8 string with no convention defined for its contents.
++ Each name is unique among all wl_output globals. The name is only
++ guaranteed to be unique for the compositor instance.
++
++ The same output name is used for all clients for a given wl_output
++ global. Thus, the name can be shared across processes to refer to a
++ specific wl_output global.
++
++ The name is not guaranteed to be persistent across sessions, thus cannot
++ be used to reliably identify an output in e.g. configuration files.
++
++ Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do
++ not assume that the name is a reflection of an underlying DRM connector,
++ X11 connection, etc.
++
++ The name event is sent after binding the output object. This event is
++ only sent once per output object, and the name does not change over the
++ lifetime of the wl_output global.
++
++ Compositors may re-use the same output name if the wl_output global is
++ destroyed and re-created later. Compositors should avoid re-using the
++ same name if possible.
++
++ The name event will be followed by a done event.
++ </description>
++ <arg name="name" type="string" summary="output name"/>
++ </event>
++
++ <event name="description" since="4">
++ <description summary="human-readable description of this output">
++ Many compositors can produce human-readable descriptions of their
++ outputs. The client may wish to know this description as well, e.g. for
++ output selection purposes.
++
++ The description is a UTF-8 string with no convention defined for its
++ contents. The description is not guaranteed to be unique among all
++ wl_output globals. Examples might include 'Foocorp 11" Display' or
++ 'Virtual X11 output via :1'.
++
++ The description event is sent after binding the output object and
++ whenever the description changes. The description is optional, and may
++ not be sent at all.
++
++ The description event will be followed by a done event.
++ </description>
++ <arg name="description" type="string" summary="output description"/>
++ </event>
++ </interface>
++
++ <interface name="wl_region" version="1">
++ <description summary="region interface">
++ A region object describes an area.
++
++ Region objects are used to describe the opaque and input
++ regions of a surface.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy region">
++ Destroy the region. This will invalidate the object ID.
++ </description>
++ </request>
++
++ <request name="add">
++ <description summary="add rectangle to region">
++ Add the specified rectangle to the region.
++ </description>
++ <arg name="x" type="int" summary="region-local x coordinate"/>
++ <arg name="y" type="int" summary="region-local y coordinate"/>
++ <arg name="width" type="int" summary="rectangle width"/>
++ <arg name="height" type="int" summary="rectangle height"/>
++ </request>
++
++ <request name="subtract">
++ <description summary="subtract rectangle from region">
++ Subtract the specified rectangle from the region.
++ </description>
++ <arg name="x" type="int" summary="region-local x coordinate"/>
++ <arg name="y" type="int" summary="region-local y coordinate"/>
++ <arg name="width" type="int" summary="rectangle width"/>
++ <arg name="height" type="int" summary="rectangle height"/>
++ </request>
++ </interface>
++
++ <interface name="wl_subcompositor" version="1">
++ <description summary="sub-surface compositing">
++ The global interface exposing sub-surface compositing capabilities.
++ A wl_surface, that has sub-surfaces associated, is called the
++ parent surface. Sub-surfaces can be arbitrarily nested and create
++ a tree of sub-surfaces.
++
++ The root surface in a tree of sub-surfaces is the main
++ surface. The main surface cannot be a sub-surface, because
++ sub-surfaces must always have a parent.
++
++ A main surface with its sub-surfaces forms a (compound) window.
++ For window management purposes, this set of wl_surface objects is
++ to be considered as a single window, and it should also behave as
++ such.
++
++ The aim of sub-surfaces is to offload some of the compositing work
++ within a window from clients to the compositor. A prime example is
++ a video player with decorations and video in separate wl_surface
++ objects. This should allow the compositor to pass YUV video buffer
++ processing to dedicated overlay hardware when possible.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="unbind from the subcompositor interface">
++ Informs the server that the client will not be using this
++ protocol object anymore. This does not affect any other
++ objects, wl_subsurface objects included.
++ </description>
++ </request>
++
++ <enum name="error">
++ <entry name="bad_surface" value="0"
++ summary="the to-be sub-surface is invalid"/>
++ </enum>
++
++ <request name="get_subsurface">
++ <description summary="give a surface the role sub-surface">
++ Create a sub-surface interface for the given surface, and
++ associate it with the given parent surface. This turns a
++ plain wl_surface into a sub-surface.
++
++ The to-be sub-surface must not already have another role, and it
++ must not have an existing wl_subsurface object. Otherwise a protocol
++ error is raised.
++
++ Adding sub-surfaces to a parent is a double-buffered operation on the
++ parent (see wl_surface.commit). The effect of adding a sub-surface
++ becomes visible on the next time the state of the parent surface is
++ applied.
++
++ This request modifies the behaviour of wl_surface.commit request on
++ the sub-surface, see the documentation on wl_subsurface interface.
++ </description>
++ <arg name="id" type="new_id" interface="wl_subsurface"
++ summary="the new sub-surface object ID"/>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="the surface to be turned into a sub-surface"/>
++ <arg name="parent" type="object" interface="wl_surface"
++ summary="the parent surface"/>
++ </request>
++ </interface>
++
++ <interface name="wl_subsurface" version="1">
++ <description summary="sub-surface interface to a wl_surface">
++ An additional interface to a wl_surface object, which has been
++ made a sub-surface. A sub-surface has one parent surface. A
++ sub-surface's size and position are not limited to that of the parent.
++ Particularly, a sub-surface is not automatically clipped to its
++ parent's area.
++
++ A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
++ and the parent surface is mapped. The order of which one happens
++ first is irrelevant. A sub-surface is hidden if the parent becomes
++ hidden, or if a NULL wl_buffer is applied. These rules apply
++ recursively through the tree of surfaces.
++
++ The behaviour of a wl_surface.commit request on a sub-surface
++ depends on the sub-surface's mode. The possible modes are
++ synchronized and desynchronized, see methods
++ wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
++ mode caches the wl_surface state to be applied when the parent's
++ state gets applied, and desynchronized mode applies the pending
++ wl_surface state directly. A sub-surface is initially in the
++ synchronized mode.
++
++ Sub-surfaces also have another kind of state, which is managed by
++ wl_subsurface requests, as opposed to wl_surface requests. This
++ state includes the sub-surface position relative to the parent
++ surface (wl_subsurface.set_position), and the stacking order of
++ the parent and its sub-surfaces (wl_subsurface.place_above and
++ .place_below). This state is applied when the parent surface's
++ wl_surface state is applied, regardless of the sub-surface's mode.
++ As the exception, set_sync and set_desync are effective immediately.
++
++ The main surface can be thought to be always in desynchronized mode,
++ since it does not have a parent in the sub-surfaces sense.
++
++ Even if a sub-surface is in desynchronized mode, it will behave as
++ in synchronized mode, if its parent surface behaves as in
++ synchronized mode. This rule is applied recursively throughout the
++ tree of surfaces. This means, that one can set a sub-surface into
++ synchronized mode, and then assume that all its child and grand-child
++ sub-surfaces are synchronized, too, without explicitly setting them.
++
++ If the wl_surface associated with the wl_subsurface is destroyed, the
++ wl_subsurface object becomes inert. Note, that destroying either object
++ takes effect immediately. If you need to synchronize the removal
++ of a sub-surface to the parent surface update, unmap the sub-surface
++ first by attaching a NULL wl_buffer, update parent, and then destroy
++ the sub-surface.
++
++ If the parent wl_surface object is destroyed, the sub-surface is
++ unmapped.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="remove sub-surface interface">
++ The sub-surface interface is removed from the wl_surface object
++ that was turned into a sub-surface with a
++ wl_subcompositor.get_subsurface request. The wl_surface's association
++ to the parent is deleted, and the wl_surface loses its role as
++ a sub-surface. The wl_surface is unmapped immediately.
++ </description>
++ </request>
++
++ <enum name="error">
++ <entry name="bad_surface" value="0"
++ summary="wl_surface is not a sibling or the parent"/>
++ </enum>
++
++ <request name="set_position">
++ <description summary="reposition the sub-surface">
++ This schedules a sub-surface position change.
++ The sub-surface will be moved so that its origin (top left
++ corner pixel) will be at the location x, y of the parent surface
++ coordinate system. The coordinates are not restricted to the parent
++ surface area. Negative values are allowed.
++
++ The scheduled coordinates will take effect whenever the state of the
++ parent surface is applied. When this happens depends on whether the
++ parent surface is in synchronized mode or not. See
++ wl_subsurface.set_sync and wl_subsurface.set_desync for details.
++
++ If more than one set_position request is invoked by the client before
++ the commit of the parent surface, the position of a new request always
++ replaces the scheduled position from any previous request.
++
++ The initial position is 0, 0.
++ </description>
++ <arg name="x" type="int" summary="x coordinate in the parent surface"/>
++ <arg name="y" type="int" summary="y coordinate in the parent surface"/>
++ </request>
++
++ <request name="place_above">
++ <description summary="restack the sub-surface">
++ This sub-surface is taken from the stack, and put back just
++ above the reference surface, changing the z-order of the sub-surfaces.
++ The reference surface must be one of the sibling surfaces, or the
++ parent surface. Using any other surface, including this sub-surface,
++ will cause a protocol error.
++
++ The z-order is double-buffered. Requests are handled in order and
++ applied immediately to a pending state. The final pending state is
++ copied to the active state the next time the state of the parent
++ surface is applied. When this happens depends on whether the parent
++ surface is in synchronized mode or not. See wl_subsurface.set_sync and
++ wl_subsurface.set_desync for details.
++
++ A new sub-surface is initially added as the top-most in the stack
++ of its siblings and parent.
++ </description>
++ <arg name="sibling" type="object" interface="wl_surface"
++ summary="the reference surface"/>
++ </request>
++
++ <request name="place_below">
++ <description summary="restack the sub-surface">
++ The sub-surface is placed just below the reference surface.
++ See wl_subsurface.place_above.
++ </description>
++ <arg name="sibling" type="object" interface="wl_surface"
++ summary="the reference surface"/>
++ </request>
++
++ <request name="set_sync">
++ <description summary="set sub-surface to synchronized mode">
++ Change the commit behaviour of the sub-surface to synchronized
++ mode, also described as the parent dependent mode.
++
++ In synchronized mode, wl_surface.commit on a sub-surface will
++ accumulate the committed state in a cache, but the state will
++ not be applied and hence will not change the compositor output.
++ The cached state is applied to the sub-surface immediately after
++ the parent surface's state is applied. This ensures atomic
++ updates of the parent and all its synchronized sub-surfaces.
++ Applying the cached state will invalidate the cache, so further
++ parent surface commits do not (re-)apply old state.
++
++ See wl_subsurface for the recursive effect of this mode.
++ </description>
++ </request>
++
++ <request name="set_desync">
++ <description summary="set sub-surface to desynchronized mode">
++ Change the commit behaviour of the sub-surface to desynchronized
++ mode, also described as independent or freely running mode.
++
++ In desynchronized mode, wl_surface.commit on a sub-surface will
++ apply the pending state directly, without caching, as happens
++ normally with a wl_surface. Calling wl_surface.commit on the
++ parent surface has no effect on the sub-surface's wl_surface
++ state. This mode allows a sub-surface to be updated on its own.
++
++ If cached state exists when wl_surface.commit is called in
++ desynchronized mode, the pending state is added to the cached
++ state, and applied as a whole. This invalidates the cache.
++
++ Note: even if a sub-surface is set to desynchronized, a parent
++ sub-surface may override it to behave as synchronized. For details,
++ see wl_subsurface.
++
++ If a surface's parent surface behaves as desynchronized, then
++ the cached state is applied on set_desync.
++ </description>
++ </request>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++#!/bin/sh -eu
++
++build_dir=build-release
++
++if ! type glab >/dev/null; then
++ echo "glab is needed to create a release"
++ exit 1
++fi
++
++case "$(git rev-parse --abbrev-ref HEAD)" in
++main | [0-9]*.[0-9]*)
++ ;;
++*)
++ echo "Not on the main or a stable branch"
++ exit 1
++esac
++
++if [ -n "$(git log @{upstream}..)" ]; then
++ echo "The main branch has unpushed commits"
++ exit 1
++fi
++
++meson_options=""
++if [ -e "$build_dir" ]; then
++ meson_options="$meson_options --wipe"
++fi
++meson setup "$build_dir" $meson_options
++
++prev_version="$(git describe --tags --abbrev=0)"
++version="$(meson introspect "$build_dir" --projectinfo | jq -r .version)"
++if [ "$version" = "$prev_version" ]; then
++ echo "Version not bumped"
++ exit 1
++fi
++
++ninja -C "$build_dir" dist
++
++archive_name="wayland-$version.tar.xz"
++archive_path="$build_dir/meson-dist/$archive_name"
++gpg --detach-sig "$archive_path"
++
++sha256="$(cd $build_dir/meson-dist && sha256sum $archive_name)"
++sha512="$(cd $build_dir/meson-dist && sha512sum $archive_name)"
++archive_url="https://gitlab.freedesktop.org/wayland/wayland/-/releases/$version/downloads/$archive_name"
++announce_path="$build_dir/meson-dist/wayland-$version-announce.eml"
++cat >"$announce_path" <<EOF
++To: <wayland-devel@lists.freedesktop.org>
++Subject: [ANNOUNCE] wayland $version
++
++`git shortlog --no-merges "$prev_version.."`
++
++git tag: $version
++
++$archive_url
++SHA256: $sha256
++SHA512: $sha512
++PGP: $archive_url.sig
++EOF
++
++echo "Release announcement written to $announce_path"
++
++echo -n "Release wayland $version? [y/N] "
++read answer
++if [ "$answer" != "y" ]; then
++ exit 1
++fi
++
++git tag -s -m "$version" "$version"
++git push --tags
++glab release create "$version" "$archive_path"* --notes ""
--- /dev/null
--- /dev/null
++To make a release of Wayland, follow these steps.
++
++ 0. Verify the test suites and codebase checks pass. All of the
++ tests should either pass or skip.
++
++ $ ninja -C build/ test
++
++ 1. Update the first stanza of meson.build to the intended version.
++
++ Then commit your changes:
++
++ $ export RELEASE_NUMBER="x.y.z"
++ $ export RELEASE_NAME="[alpha|beta|RC1|RC2|official|point]"
++ $ git status
++ $ git commit meson.build -m "build: bump to version $RELEASE_NUMBER for the $RELEASE_NAME release"
++ $ git push
++
++ 2. Run the release.sh script to generate the tarballs, sign and
++ upload them, and generate a release announcement template.
++
++ 3. Compose the release announcements. The script will generate a
++ wayland-x.y.z-announce.eml file with a list of changes and tags.
++ Prepend it with a human-readable listing of the most notable
++ changes. For x.y.0 releases, indicate the schedule for the x.y+1.0
++ release.
++
++ 4. PGP sign the release announcements and send them to
++ wayland-devel@lists.freedesktop.org
++
++ 5. Update releases.html in wayland-web with links to tarballs and
++ the release email URL.
++
++ The wl_register_release script in wayland-web will generate an HTML
++ snippet that can be pasted into releases.html (or e.g. in emacs
++ insert it via "C-u M-! scripts/wl_register_release x.y.z") and
++ customized.
++
++ Once satisfied:
++
++ $ git commit ./releases.html -m "releases: Add ${RELEASE_NUMBER} release"
++ $ git push
++ $ ./deploy
++
++For x.y.0 releases, also create the release series x.y branch. The x.y
++branch is for bug fixes and conservative changes to the x.y.0 release,
++and is where we create x.y.z releases from. Creating the x.y branch
++opens up master for new development and lets new development move on.
++We've done this both after the x.y.0 release (to focus development on
++bug fixing for the x.y.1 release for a little longer) or before the
++x.y.0 release (like we did with the 1.5.0 release, to unblock master
++development early).
++
++ $ git branch x.y [sha]
++ $ git push origin x.y
++
++The master branch's meson.build version should always be (at least)
++x.y.90, with x.y being the most recent stable branch. The stable
++branch's meson.build version is just whatever was most recently
++released from that branch.
++
++For stable branches, we commit fixes to master first, then cherry-pick
++them back to the stable branch.
--- /dev/null
--- /dev/null
++*.dtd.embed
++/wayland-version.h
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ * Copyright © 2013 Jason Ekstrand
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++
++#include <math.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <string.h>
++#include <stdio.h>
++#include <errno.h>
++#include <sys/uio.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <time.h>
++#include <ffi.h>
++
++#include "wayland-util.h"
++#include "wayland-private.h"
++#include "wayland-os.h"
++
++static inline uint32_t
++div_roundup(uint32_t n, size_t a)
++{
++ /* The cast to uint64_t is necessary to prevent overflow when rounding
++ * values close to UINT32_MAX. After the division it is again safe to
++ * cast back to uint32_t.
++ */
++ return (uint32_t) (((uint64_t) n + (a - 1)) / a);
++}
++
++struct wl_ring_buffer {
++ char data[4096];
++ uint32_t head, tail;
++};
++
++#define MASK(i) ((i) & 4095)
++
++#define MAX_FDS_OUT 28
++#define CLEN (CMSG_LEN(MAX_FDS_OUT * sizeof(int32_t)))
++
++struct wl_connection {
++ struct wl_ring_buffer in, out;
++ struct wl_ring_buffer fds_in, fds_out;
++ int fd;
++ int want_flush;
++};
++
++static int
++ring_buffer_put(struct wl_ring_buffer *b, const void *data, size_t count)
++{
++ uint32_t head, size;
++
++ if (count > sizeof(b->data)) {
++ wl_log("Data too big for buffer (%d > %d).\n",
++ count, sizeof(b->data));
++ errno = E2BIG;
++ return -1;
++ }
++
++ head = MASK(b->head);
++ if (head + count <= sizeof b->data) {
++ memcpy(b->data + head, data, count);
++ } else {
++ size = sizeof b->data - head;
++ memcpy(b->data + head, data, size);
++ memcpy(b->data, (const char *) data + size, count - size);
++ }
++
++ b->head += count;
++
++ return 0;
++}
++
++static void
++ring_buffer_put_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count)
++{
++ uint32_t head, tail;
++
++ head = MASK(b->head);
++ tail = MASK(b->tail);
++ if (head < tail) {
++ iov[0].iov_base = b->data + head;
++ iov[0].iov_len = tail - head;
++ *count = 1;
++ } else if (tail == 0) {
++ iov[0].iov_base = b->data + head;
++ iov[0].iov_len = sizeof b->data - head;
++ *count = 1;
++ } else {
++ iov[0].iov_base = b->data + head;
++ iov[0].iov_len = sizeof b->data - head;
++ iov[1].iov_base = b->data;
++ iov[1].iov_len = tail;
++ *count = 2;
++ }
++}
++
++static void
++ring_buffer_get_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count)
++{
++ uint32_t head, tail;
++
++ head = MASK(b->head);
++ tail = MASK(b->tail);
++ if (tail < head) {
++ iov[0].iov_base = b->data + tail;
++ iov[0].iov_len = head - tail;
++ *count = 1;
++ } else if (head == 0) {
++ iov[0].iov_base = b->data + tail;
++ iov[0].iov_len = sizeof b->data - tail;
++ *count = 1;
++ } else {
++ iov[0].iov_base = b->data + tail;
++ iov[0].iov_len = sizeof b->data - tail;
++ iov[1].iov_base = b->data;
++ iov[1].iov_len = head;
++ *count = 2;
++ }
++}
++
++static void
++ring_buffer_copy(struct wl_ring_buffer *b, void *data, size_t count)
++{
++ uint32_t tail, size;
++
++ tail = MASK(b->tail);
++ if (tail + count <= sizeof b->data) {
++ memcpy(data, b->data + tail, count);
++ } else {
++ size = sizeof b->data - tail;
++ memcpy(data, b->data + tail, size);
++ memcpy((char *) data + size, b->data, count - size);
++ }
++}
++
++static uint32_t
++ring_buffer_size(struct wl_ring_buffer *b)
++{
++ return b->head - b->tail;
++}
++
++struct wl_connection *
++wl_connection_create(int fd)
++{
++ struct wl_connection *connection;
++
++ connection = zalloc(sizeof *connection);
++ if (connection == NULL)
++ return NULL;
++
++ connection->fd = fd;
++
++ return connection;
++}
++
++static void
++close_fds(struct wl_ring_buffer *buffer, int max)
++{
++ int32_t fds[sizeof(buffer->data) / sizeof(int32_t)], i, count;
++ size_t size;
++
++ size = ring_buffer_size(buffer);
++ if (size == 0)
++ return;
++
++ ring_buffer_copy(buffer, fds, size);
++ count = size / sizeof fds[0];
++ if (max > 0 && max < count)
++ count = max;
++ size = count * sizeof fds[0];
++ for (i = 0; i < count; i++)
++ close(fds[i]);
++ buffer->tail += size;
++}
++
++void
++wl_connection_close_fds_in(struct wl_connection *connection, int max)
++{
++ close_fds(&connection->fds_in, max);
++}
++
++int
++wl_connection_destroy(struct wl_connection *connection)
++{
++ int fd = connection->fd;
++
++ close_fds(&connection->fds_out, -1);
++ close_fds(&connection->fds_in, -1);
++ free(connection);
++
++ return fd;
++}
++
++void
++wl_connection_copy(struct wl_connection *connection, void *data, size_t size)
++{
++ ring_buffer_copy(&connection->in, data, size);
++}
++
++void
++wl_connection_consume(struct wl_connection *connection, size_t size)
++{
++ connection->in.tail += size;
++}
++
++static void
++build_cmsg(struct wl_ring_buffer *buffer, char *data, size_t *clen)
++{
++ struct cmsghdr *cmsg;
++ size_t size;
++
++ size = ring_buffer_size(buffer);
++ if (size > MAX_FDS_OUT * sizeof(int32_t))
++ size = MAX_FDS_OUT * sizeof(int32_t);
++
++ if (size > 0) {
++ cmsg = (struct cmsghdr *) data;
++ cmsg->cmsg_level = SOL_SOCKET;
++ cmsg->cmsg_type = SCM_RIGHTS;
++ cmsg->cmsg_len = CMSG_LEN(size);
++ ring_buffer_copy(buffer, CMSG_DATA(cmsg), size);
++ *clen = cmsg->cmsg_len;
++ } else {
++ *clen = 0;
++ }
++}
++
++static int
++decode_cmsg(struct wl_ring_buffer *buffer, struct msghdr *msg)
++{
++ struct cmsghdr *cmsg;
++ size_t size, max, i;
++ int overflow = 0;
++
++ for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
++ cmsg = CMSG_NXTHDR(msg, cmsg)) {
++ if (cmsg->cmsg_level != SOL_SOCKET ||
++ cmsg->cmsg_type != SCM_RIGHTS)
++ continue;
++
++ size = cmsg->cmsg_len - CMSG_LEN(0);
++ max = sizeof(buffer->data) - ring_buffer_size(buffer);
++ if (size > max || overflow) {
++ overflow = 1;
++ size /= sizeof(int32_t);
++ for (i = 0; i < size; i++)
++ close(((int*)CMSG_DATA(cmsg))[i]);
++ } else if (ring_buffer_put(buffer, CMSG_DATA(cmsg), size) < 0) {
++ return -1;
++ }
++ }
++
++ if (overflow) {
++ errno = EOVERFLOW;
++ return -1;
++ }
++
++ return 0;
++}
++
++int
++wl_connection_flush(struct wl_connection *connection)
++{
++ struct iovec iov[2];
++ struct msghdr msg = {0};
++ char cmsg[CLEN];
++ int len = 0, count;
++ size_t clen;
++ uint32_t tail;
++
++ if (!connection->want_flush)
++ return 0;
++
++ tail = connection->out.tail;
++ while (connection->out.head - connection->out.tail > 0) {
++ ring_buffer_get_iov(&connection->out, iov, &count);
++
++ build_cmsg(&connection->fds_out, cmsg, &clen);
++
++ msg.msg_iov = iov;
++ msg.msg_iovlen = count;
++ msg.msg_control = (clen > 0) ? cmsg : NULL;
++ msg.msg_controllen = clen;
++
++ do {
++ len = sendmsg(connection->fd, &msg,
++ MSG_NOSIGNAL | MSG_DONTWAIT);
++ } while (len == -1 && errno == EINTR);
++
++ if (len == -1)
++ return -1;
++
++ close_fds(&connection->fds_out, MAX_FDS_OUT);
++
++ connection->out.tail += len;
++ }
++
++ connection->want_flush = 0;
++
++ return connection->out.head - tail;
++}
++
++uint32_t
++wl_connection_pending_input(struct wl_connection *connection)
++{
++ return ring_buffer_size(&connection->in);
++}
++
++int
++wl_connection_read(struct wl_connection *connection)
++{
++ struct iovec iov[2];
++ struct msghdr msg;
++ char cmsg[CLEN];
++ int len, count, ret;
++
++ if (ring_buffer_size(&connection->in) >= sizeof(connection->in.data)) {
++ errno = EOVERFLOW;
++ return -1;
++ }
++
++ ring_buffer_put_iov(&connection->in, iov, &count);
++
++ msg.msg_name = NULL;
++ msg.msg_namelen = 0;
++ msg.msg_iov = iov;
++ msg.msg_iovlen = count;
++ msg.msg_control = cmsg;
++ msg.msg_controllen = sizeof cmsg;
++ msg.msg_flags = 0;
++
++ do {
++ len = wl_os_recvmsg_cloexec(connection->fd, &msg, MSG_DONTWAIT);
++ } while (len < 0 && errno == EINTR);
++
++ if (len <= 0)
++ return len;
++
++ ret = decode_cmsg(&connection->fds_in, &msg);
++ if (ret)
++ return -1;
++
++ connection->in.head += len;
++
++ return wl_connection_pending_input(connection);
++}
++
++int
++wl_connection_write(struct wl_connection *connection,
++ const void *data, size_t count)
++{
++ if (connection->out.head - connection->out.tail +
++ count > ARRAY_LENGTH(connection->out.data)) {
++ connection->want_flush = 1;
++ if (wl_connection_flush(connection) < 0)
++ return -1;
++ }
++
++ if (ring_buffer_put(&connection->out, data, count) < 0)
++ return -1;
++
++ connection->want_flush = 1;
++
++ return 0;
++}
++
++int
++wl_connection_queue(struct wl_connection *connection,
++ const void *data, size_t count)
++{
++ if (connection->out.head - connection->out.tail +
++ count > ARRAY_LENGTH(connection->out.data)) {
++ connection->want_flush = 1;
++ if (wl_connection_flush(connection) < 0)
++ return -1;
++ }
++
++ return ring_buffer_put(&connection->out, data, count);
++}
++
++int
++wl_message_count_arrays(const struct wl_message *message)
++{
++ int i, arrays;
++
++ for (i = 0, arrays = 0; message->signature[i]; i++) {
++ if (message->signature[i] == 'a')
++ arrays++;
++ }
++
++ return arrays;
++}
++
++int
++wl_connection_get_fd(struct wl_connection *connection)
++{
++ return connection->fd;
++}
++
++static int
++wl_connection_put_fd(struct wl_connection *connection, int32_t fd)
++{
++ if (ring_buffer_size(&connection->fds_out) == MAX_FDS_OUT * sizeof fd) {
++ connection->want_flush = 1;
++ if (wl_connection_flush(connection) < 0)
++ return -1;
++ }
++
++ return ring_buffer_put(&connection->fds_out, &fd, sizeof fd);
++}
++
++const char *
++get_next_argument(const char *signature, struct argument_details *details)
++{
++ details->nullable = 0;
++ for(; *signature; ++signature) {
++ switch(*signature) {
++ case 'i':
++ case 'u':
++ case 'f':
++ case 's':
++ case 'o':
++ case 'n':
++ case 'a':
++ case 'h':
++ details->type = *signature;
++ return signature + 1;
++ case '?':
++ details->nullable = 1;
++ }
++ }
++ details->type = '\0';
++ return signature;
++}
++
++int
++arg_count_for_signature(const char *signature)
++{
++ int count = 0;
++ for(; *signature; ++signature) {
++ switch(*signature) {
++ case 'i':
++ case 'u':
++ case 'f':
++ case 's':
++ case 'o':
++ case 'n':
++ case 'a':
++ case 'h':
++ ++count;
++ }
++ }
++ return count;
++}
++
++int
++wl_message_get_since(const struct wl_message *message)
++{
++ int since;
++
++ since = atoi(message->signature);
++
++ if (since == 0)
++ since = 1;
++
++ return since;
++}
++
++void
++wl_argument_from_va_list(const char *signature, union wl_argument *args,
++ int count, va_list ap)
++{
++ int i;
++ const char *sig_iter;
++ struct argument_details arg;
++
++ sig_iter = signature;
++ for (i = 0; i < count; i++) {
++ sig_iter = get_next_argument(sig_iter, &arg);
++
++ switch(arg.type) {
++ case 'i':
++ args[i].i = va_arg(ap, int32_t);
++ break;
++ case 'u':
++ args[i].u = va_arg(ap, uint32_t);
++ break;
++ case 'f':
++ args[i].f = va_arg(ap, wl_fixed_t);
++ break;
++ case 's':
++ args[i].s = va_arg(ap, const char *);
++ break;
++ case 'o':
++ args[i].o = va_arg(ap, struct wl_object *);
++ break;
++ case 'n':
++ args[i].o = va_arg(ap, struct wl_object *);
++ break;
++ case 'a':
++ args[i].a = va_arg(ap, struct wl_array *);
++ break;
++ case 'h':
++ args[i].h = va_arg(ap, int32_t);
++ break;
++ case '\0':
++ return;
++ }
++ }
++}
++
++static void
++wl_closure_clear_fds(struct wl_closure *closure)
++{
++ const char *signature = closure->message->signature;
++ struct argument_details arg;
++ int i;
++
++ for (i = 0; i < closure->count; i++) {
++ signature = get_next_argument(signature, &arg);
++ if (arg.type == 'h')
++ closure->args[i].h = -1;
++ }
++}
++
++static struct wl_closure *
++wl_closure_init(const struct wl_message *message, uint32_t size,
++ int *num_arrays, union wl_argument *args)
++{
++ struct wl_closure *closure;
++ int count;
++
++ count = arg_count_for_signature(message->signature);
++ if (count > WL_CLOSURE_MAX_ARGS) {
++ wl_log("too many args (%d)\n", count);
++ errno = EINVAL;
++ return NULL;
++ }
++
++ if (size) {
++ *num_arrays = wl_message_count_arrays(message);
++ closure = zalloc(sizeof *closure + size +
++ *num_arrays * sizeof(struct wl_array));
++ } else {
++ closure = zalloc(sizeof *closure);
++ }
++
++ if (!closure) {
++ errno = ENOMEM;
++ return NULL;
++ }
++
++ if (args)
++ memcpy(closure->args, args, count * sizeof *args);
++
++ closure->message = message;
++ closure->count = count;
++
++ /* Set these all to -1 so we can close any that have been
++ * set to a real value during wl_closure_destroy().
++ * We may have copied a bunch of fds into the closure with
++ * memcpy previously, but those are undup()d client fds
++ * that we would have replaced anyway.
++ */
++ wl_closure_clear_fds(closure);
++
++ return closure;
++}
++
++struct wl_closure *
++wl_closure_marshal(struct wl_object *sender, uint32_t opcode,
++ union wl_argument *args,
++ const struct wl_message *message)
++{
++ struct wl_closure *closure;
++ struct wl_object *object;
++ int i, count, fd, dup_fd;
++ const char *signature;
++ struct argument_details arg;
++
++ closure = wl_closure_init(message, 0, NULL, args);
++ if (closure == NULL)
++ return NULL;
++
++ count = closure->count;
++
++ signature = message->signature;
++ for (i = 0; i < count; i++) {
++ signature = get_next_argument(signature, &arg);
++
++ switch (arg.type) {
++ case 'f':
++ case 'u':
++ case 'i':
++ break;
++ case 's':
++ if (!arg.nullable && args[i].s == NULL)
++ goto err_null;
++ break;
++ case 'o':
++ if (!arg.nullable && args[i].o == NULL)
++ goto err_null;
++ break;
++ case 'n':
++ object = args[i].o;
++ if (object == NULL)
++ goto err_null;
++
++ closure->args[i].n = object ? object->id : 0;
++ break;
++ case 'a':
++ if (args[i].a == NULL)
++ goto err_null;
++ break;
++ case 'h':
++ fd = args[i].h;
++ dup_fd = wl_os_dupfd_cloexec(fd, 0);
++ if (dup_fd < 0) {
++ wl_closure_destroy(closure);
++ wl_log("error marshalling arguments for %s: dup failed: %s\n",
++ message->name, strerror(errno));
++ return NULL;
++ }
++ closure->args[i].h = dup_fd;
++ break;
++ default:
++ wl_abort("unhandled format code: '%c'\n", arg.type);
++ break;
++ }
++ }
++
++ closure->sender_id = sender->id;
++ closure->opcode = opcode;
++
++ return closure;
++
++err_null:
++ wl_closure_destroy(closure);
++ wl_log("error marshalling arguments for %s (signature %s): "
++ "null value passed for arg %i\n", message->name,
++ message->signature, i);
++ errno = EINVAL;
++ return NULL;
++}
++
++struct wl_closure *
++wl_closure_vmarshal(struct wl_object *sender, uint32_t opcode, va_list ap,
++ const struct wl_message *message)
++{
++ union wl_argument args[WL_CLOSURE_MAX_ARGS];
++
++ wl_argument_from_va_list(message->signature, args,
++ WL_CLOSURE_MAX_ARGS, ap);
++
++ return wl_closure_marshal(sender, opcode, args, message);
++}
++
++struct wl_closure *
++wl_connection_demarshal(struct wl_connection *connection,
++ uint32_t size,
++ struct wl_map *objects,
++ const struct wl_message *message)
++{
++ uint32_t *p, *next, *end, length, length_in_u32, id;
++ int fd;
++ char *s;
++ int i, count, num_arrays;
++ const char *signature;
++ struct argument_details arg;
++ struct wl_closure *closure;
++ struct wl_array *array_extra;
++
++ /* Space for sender_id and opcode */
++ if (size < 2 * sizeof *p) {
++ wl_log("message too short, invalid header\n");
++ wl_connection_consume(connection, size);
++ errno = EINVAL;
++ return NULL;
++ }
++
++ closure = wl_closure_init(message, size, &num_arrays, NULL);
++ if (closure == NULL) {
++ wl_connection_consume(connection, size);
++ return NULL;
++ }
++
++ count = closure->count;
++
++ array_extra = closure->extra;
++ p = (uint32_t *)(closure->extra + num_arrays);
++ end = p + size / sizeof *p;
++
++ wl_connection_copy(connection, p, size);
++ closure->sender_id = *p++;
++ closure->opcode = *p++ & 0x0000ffff;
++
++ signature = message->signature;
++ for (i = 0; i < count; i++) {
++ signature = get_next_argument(signature, &arg);
++
++ if (arg.type != 'h' && p + 1 > end) {
++ wl_log("message too short, "
++ "object (%d), message %s(%s)\n",
++ closure->sender_id, message->name,
++ message->signature);
++ errno = EINVAL;
++ goto err;
++ }
++
++ switch (arg.type) {
++ case 'u':
++ closure->args[i].u = *p++;
++ break;
++ case 'i':
++ closure->args[i].i = *p++;
++ break;
++ case 'f':
++ closure->args[i].f = *p++;
++ break;
++ case 's':
++ length = *p++;
++
++ if (length == 0 && !arg.nullable) {
++ wl_log("NULL string received on non-nullable "
++ "type, message %s(%s)\n", message->name,
++ message->signature);
++ errno = EINVAL;
++ goto err;
++ }
++ if (length == 0) {
++ closure->args[i].s = NULL;
++ break;
++ }
++
++ length_in_u32 = div_roundup(length, sizeof *p);
++ if ((uint32_t) (end - p) < length_in_u32) {
++ wl_log("message too short, "
++ "object (%d), message %s(%s)\n",
++ closure->sender_id, message->name,
++ message->signature);
++ errno = EINVAL;
++ goto err;
++ }
++ next = p + length_in_u32;
++
++ s = (char *) p;
++
++ if (length > 0 && s[length - 1] != '\0') {
++ wl_log("string not nul-terminated, "
++ "message %s(%s)\n",
++ message->name, message->signature);
++ errno = EINVAL;
++ goto err;
++ }
++
++ closure->args[i].s = s;
++ p = next;
++ break;
++ case 'o':
++ id = *p++;
++ closure->args[i].n = id;
++
++ if (id == 0 && !arg.nullable) {
++ wl_log("NULL object received on non-nullable "
++ "type, message %s(%s)\n", message->name,
++ message->signature);
++ errno = EINVAL;
++ goto err;
++ }
++ break;
++ case 'n':
++ id = *p++;
++ closure->args[i].n = id;
++
++ if (id == 0) {
++ wl_log("NULL new ID received on non-nullable "
++ "type, message %s(%s)\n", message->name,
++ message->signature);
++ errno = EINVAL;
++ goto err;
++ }
++
++ if (wl_map_reserve_new(objects, id) < 0) {
++ if (errno == EINVAL) {
++ wl_log("not a valid new object id (%u), "
++ "message %s(%s)\n", id,
++ message->name,
++ message->signature);
++ }
++ goto err;
++ }
++
++ break;
++ case 'a':
++ length = *p++;
++
++ length_in_u32 = div_roundup(length, sizeof *p);
++ if ((uint32_t) (end - p) < length_in_u32) {
++ wl_log("message too short, "
++ "object (%d), message %s(%s)\n",
++ closure->sender_id, message->name,
++ message->signature);
++ errno = EINVAL;
++ goto err;
++ }
++ next = p + length_in_u32;
++
++ array_extra->size = length;
++ array_extra->alloc = 0;
++ array_extra->data = p;
++
++ closure->args[i].a = array_extra++;
++ p = next;
++ break;
++ case 'h':
++ if (connection->fds_in.tail == connection->fds_in.head) {
++ wl_log("file descriptor expected, "
++ "object (%d), message %s(%s)\n",
++ closure->sender_id, message->name,
++ message->signature);
++ errno = EINVAL;
++ goto err;
++ }
++
++ ring_buffer_copy(&connection->fds_in, &fd, sizeof fd);
++ connection->fds_in.tail += sizeof fd;
++ closure->args[i].h = fd;
++ break;
++ default:
++ wl_abort("unknown type\n");
++ break;
++ }
++ }
++
++ wl_connection_consume(connection, size);
++
++ return closure;
++
++ err:
++ wl_closure_destroy(closure);
++ wl_connection_consume(connection, size);
++
++ return NULL;
++}
++
++bool
++wl_object_is_zombie(struct wl_map *map, uint32_t id)
++{
++ uint32_t flags;
++
++ /* Zombie objects only exist on the client side. */
++ if (map->side == WL_MAP_SERVER_SIDE)
++ return false;
++
++ /* Zombie objects can only have been created by the client. */
++ if (id >= WL_SERVER_ID_START)
++ return false;
++
++ flags = wl_map_lookup_flags(map, id);
++ return !!(flags & WL_MAP_ENTRY_ZOMBIE);
++}
++
++int
++wl_closure_lookup_objects(struct wl_closure *closure, struct wl_map *objects)
++{
++ struct wl_object *object;
++ const struct wl_message *message;
++ const char *signature;
++ struct argument_details arg;
++ int i, count;
++ uint32_t id;
++
++ message = closure->message;
++ signature = message->signature;
++ count = arg_count_for_signature(signature);
++ for (i = 0; i < count; i++) {
++ signature = get_next_argument(signature, &arg);
++ switch (arg.type) {
++ case 'o':
++ id = closure->args[i].n;
++ closure->args[i].o = NULL;
++
++ object = wl_map_lookup(objects, id);
++ if (wl_object_is_zombie(objects, id)) {
++ /* references object we've already
++ * destroyed client side */
++ object = NULL;
++ } else if (object == NULL && id != 0) {
++ wl_log("unknown object (%u), message %s(%s)\n",
++ id, message->name, message->signature);
++ errno = EINVAL;
++ return -1;
++ }
++
++ if (object != NULL && message->types[i] != NULL &&
++ !wl_interface_equal((object)->interface,
++ message->types[i])) {
++ wl_log("invalid object (%u), type (%s), "
++ "message %s(%s)\n",
++ id, (object)->interface->name,
++ message->name, message->signature);
++ errno = EINVAL;
++ return -1;
++ }
++ closure->args[i].o = object;
++ }
++ }
++
++ return 0;
++}
++
++static void
++convert_arguments_to_ffi(const char *signature, uint32_t flags,
++ union wl_argument *args,
++ int count, ffi_type **ffi_types, void** ffi_args)
++{
++ int i;
++ const char *sig_iter;
++ struct argument_details arg;
++
++ sig_iter = signature;
++ for (i = 0; i < count; i++) {
++ sig_iter = get_next_argument(sig_iter, &arg);
++
++ switch(arg.type) {
++ case 'i':
++ ffi_types[i] = &ffi_type_sint32;
++ ffi_args[i] = &args[i].i;
++ break;
++ case 'u':
++ ffi_types[i] = &ffi_type_uint32;
++ ffi_args[i] = &args[i].u;
++ break;
++ case 'f':
++ ffi_types[i] = &ffi_type_sint32;
++ ffi_args[i] = &args[i].f;
++ break;
++ case 's':
++ ffi_types[i] = &ffi_type_pointer;
++ ffi_args[i] = &args[i].s;
++ break;
++ case 'o':
++ ffi_types[i] = &ffi_type_pointer;
++ ffi_args[i] = &args[i].o;
++ break;
++ case 'n':
++ if (flags & WL_CLOSURE_INVOKE_CLIENT) {
++ ffi_types[i] = &ffi_type_pointer;
++ ffi_args[i] = &args[i].o;
++ } else {
++ ffi_types[i] = &ffi_type_uint32;
++ ffi_args[i] = &args[i].n;
++ }
++ break;
++ case 'a':
++ ffi_types[i] = &ffi_type_pointer;
++ ffi_args[i] = &args[i].a;
++ break;
++ case 'h':
++ ffi_types[i] = &ffi_type_sint32;
++ ffi_args[i] = &args[i].h;
++ break;
++ default:
++ wl_abort("unknown type\n");
++ break;
++ }
++ }
++}
++
++void
++wl_closure_invoke(struct wl_closure *closure, uint32_t flags,
++ struct wl_object *target, uint32_t opcode, void *data)
++{
++ int count;
++ ffi_cif cif;
++ ffi_type *ffi_types[WL_CLOSURE_MAX_ARGS + 2];
++ void * ffi_args[WL_CLOSURE_MAX_ARGS + 2];
++ void (* const *implementation)(void);
++
++ count = arg_count_for_signature(closure->message->signature);
++
++ ffi_types[0] = &ffi_type_pointer;
++ ffi_args[0] = &data;
++ ffi_types[1] = &ffi_type_pointer;
++ ffi_args[1] = ⌖
++
++ convert_arguments_to_ffi(closure->message->signature, flags, closure->args,
++ count, ffi_types + 2, ffi_args + 2);
++
++ ffi_prep_cif(&cif, FFI_DEFAULT_ABI,
++ count + 2, &ffi_type_void, ffi_types);
++
++ implementation = target->implementation;
++ if (!implementation[opcode]) {
++ wl_abort("listener function for opcode %u of %s is NULL\n",
++ opcode, target->interface->name);
++ }
++ ffi_call(&cif, implementation[opcode], NULL, ffi_args);
++
++ wl_closure_clear_fds(closure);
++}
++
++void
++wl_closure_dispatch(struct wl_closure *closure, wl_dispatcher_func_t dispatcher,
++ struct wl_object *target, uint32_t opcode)
++{
++ dispatcher(target->implementation, target, opcode, closure->message,
++ closure->args);
++
++ wl_closure_clear_fds(closure);
++}
++
++static int
++copy_fds_to_connection(struct wl_closure *closure,
++ struct wl_connection *connection)
++{
++ const struct wl_message *message = closure->message;
++ uint32_t i, count;
++ struct argument_details arg;
++ const char *signature = message->signature;
++ int fd;
++
++ count = arg_count_for_signature(signature);
++ for (i = 0; i < count; i++) {
++ signature = get_next_argument(signature, &arg);
++ if (arg.type != 'h')
++ continue;
++
++ fd = closure->args[i].h;
++ if (wl_connection_put_fd(connection, fd)) {
++ wl_log("request could not be marshaled: "
++ "can't send file descriptor\n");
++ return -1;
++ }
++ closure->args[i].h = -1;
++ }
++
++ return 0;
++}
++
++
++static uint32_t
++buffer_size_for_closure(struct wl_closure *closure)
++{
++ const struct wl_message *message = closure->message;
++ int i, count;
++ struct argument_details arg;
++ const char *signature;
++ uint32_t size, buffer_size = 0;
++
++ signature = message->signature;
++ count = arg_count_for_signature(signature);
++ for (i = 0; i < count; i++) {
++ signature = get_next_argument(signature, &arg);
++
++ switch (arg.type) {
++ case 'h':
++ break;
++ case 'u':
++ case 'i':
++ case 'f':
++ case 'o':
++ case 'n':
++ buffer_size++;
++ break;
++ case 's':
++ if (closure->args[i].s == NULL) {
++ buffer_size++;
++ break;
++ }
++
++ size = strlen(closure->args[i].s) + 1;
++ buffer_size += 1 + div_roundup(size, sizeof(uint32_t));
++ break;
++ case 'a':
++ if (closure->args[i].a == NULL) {
++ buffer_size++;
++ break;
++ }
++
++ size = closure->args[i].a->size;
++ buffer_size += (1 + div_roundup(size, sizeof(uint32_t)));
++ break;
++ default:
++ break;
++ }
++ }
++
++ return buffer_size + 2;
++}
++
++static int
++serialize_closure(struct wl_closure *closure, uint32_t *buffer,
++ size_t buffer_count)
++{
++ const struct wl_message *message = closure->message;
++ unsigned int i, count, size;
++ uint32_t *p, *end;
++ struct argument_details arg;
++ const char *signature;
++
++ if (buffer_count < 2)
++ goto overflow;
++
++ p = buffer + 2;
++ end = buffer + buffer_count;
++
++ signature = message->signature;
++ count = arg_count_for_signature(signature);
++ for (i = 0; i < count; i++) {
++ signature = get_next_argument(signature, &arg);
++
++ if (arg.type == 'h')
++ continue;
++
++ if (p + 1 > end)
++ goto overflow;
++
++ switch (arg.type) {
++ case 'u':
++ *p++ = closure->args[i].u;
++ break;
++ case 'i':
++ *p++ = closure->args[i].i;
++ break;
++ case 'f':
++ *p++ = closure->args[i].f;
++ break;
++ case 'o':
++ *p++ = closure->args[i].o ? closure->args[i].o->id : 0;
++ break;
++ case 'n':
++ *p++ = closure->args[i].n;
++ break;
++ case 's':
++ if (closure->args[i].s == NULL) {
++ *p++ = 0;
++ break;
++ }
++
++ size = strlen(closure->args[i].s) + 1;
++ *p++ = size;
++
++ if (p + div_roundup(size, sizeof *p) > end)
++ goto overflow;
++
++ memcpy(p, closure->args[i].s, size);
++ p += div_roundup(size, sizeof *p);
++ break;
++ case 'a':
++ if (closure->args[i].a == NULL) {
++ *p++ = 0;
++ break;
++ }
++
++ size = closure->args[i].a->size;
++ *p++ = size;
++
++ if (p + div_roundup(size, sizeof *p) > end)
++ goto overflow;
++
++ memcpy(p, closure->args[i].a->data, size);
++ p += div_roundup(size, sizeof *p);
++ break;
++ default:
++ break;
++ }
++ }
++
++ size = (p - buffer) * sizeof *p;
++
++ buffer[0] = closure->sender_id;
++ buffer[1] = size << 16 | (closure->opcode & 0x0000ffff);
++
++ return size;
++
++overflow:
++ errno = ERANGE;
++ return -1;
++}
++
++int
++wl_closure_send(struct wl_closure *closure, struct wl_connection *connection)
++{
++ int size;
++ uint32_t buffer_size;
++ uint32_t *buffer;
++ int result;
++
++ if (copy_fds_to_connection(closure, connection))
++ return -1;
++
++ buffer_size = buffer_size_for_closure(closure);
++ buffer = zalloc(buffer_size * sizeof buffer[0]);
++ if (buffer == NULL)
++ return -1;
++
++ size = serialize_closure(closure, buffer, buffer_size);
++ if (size < 0) {
++ free(buffer);
++ return -1;
++ }
++
++ result = wl_connection_write(connection, buffer, size);
++ free(buffer);
++
++ return result;
++}
++
++int
++wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
++{
++ int size;
++ uint32_t buffer_size;
++ uint32_t *buffer;
++ int result;
++
++ if (copy_fds_to_connection(closure, connection))
++ return -1;
++
++ buffer_size = buffer_size_for_closure(closure);
++ buffer = malloc(buffer_size * sizeof buffer[0]);
++ if (buffer == NULL)
++ return -1;
++
++ size = serialize_closure(closure, buffer, buffer_size);
++ if (size < 0) {
++ free(buffer);
++ return -1;
++ }
++
++ result = wl_connection_queue(connection, buffer, size);
++ free(buffer);
++
++ return result;
++}
++
++void
++wl_closure_print(struct wl_closure *closure, struct wl_object *target,
++ int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg))
++{
++ int i;
++ struct argument_details arg;
++ const char *signature = closure->message->signature;
++ struct timespec tp;
++ unsigned int time;
++ uint32_t nval;
++ FILE *f;
++ char *buffer;
++ size_t buffer_length;
++
++ f = open_memstream(&buffer, &buffer_length);
++ if (f == NULL)
++ return;
++
++ clock_gettime(CLOCK_REALTIME, &tp);
++ time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
++
++ fprintf(f, "[%7u.%03u] %s%s%s@%u.%s(",
++ time / 1000, time % 1000,
++ discarded ? "discarded " : "",
++ send ? " -> " : "",
++ target->interface->name, target->id,
++ closure->message->name);
++
++ for (i = 0; i < closure->count; i++) {
++ signature = get_next_argument(signature, &arg);
++ if (i > 0)
++ fprintf(f, ", ");
++
++ switch (arg.type) {
++ case 'u':
++ fprintf(f, "%u", closure->args[i].u);
++ break;
++ case 'i':
++ fprintf(f, "%d", closure->args[i].i);
++ break;
++ case 'f':
++ /* The magic number 390625 is 1e8 / 256 */
++ if (closure->args[i].f >= 0) {
++ fprintf(f, "%d.%08d",
++ closure->args[i].f / 256,
++ 390625 * (closure->args[i].f % 256));
++ } else {
++
++ fprintf(f, "-%d.%08d",
++ closure->args[i].f / -256,
++ -390625 * (closure->args[i].f % 256));
++ }
++ break;
++ case 's':
++ if (closure->args[i].s)
++ fprintf(f, "\"%s\"", closure->args[i].s);
++ else
++ fprintf(f, "nil");
++ break;
++ case 'o':
++ if (closure->args[i].o)
++ fprintf(f, "%s@%u",
++ closure->args[i].o->interface->name,
++ closure->args[i].o->id);
++ else
++ fprintf(f, "nil");
++ break;
++ case 'n':
++ if (n_parse)
++ nval = n_parse(&closure->args[i]);
++ else
++ nval = closure->args[i].n;
++
++ fprintf(f, "new id %s@",
++ (closure->message->types[i]) ?
++ closure->message->types[i]->name :
++ "[unknown]");
++ if (nval != 0)
++ fprintf(f, "%u", nval);
++ else
++ fprintf(f, "nil");
++ break;
++ case 'a':
++ fprintf(f, "array[%zu]", closure->args[i].a->size);
++ break;
++ case 'h':
++ fprintf(f, "fd %d", closure->args[i].h);
++ break;
++ }
++ }
++
++ fprintf(f, ")\n");
++
++ if (fclose(f) == 0) {
++ fprintf(stderr, "%s", buffer);
++ free(buffer);
++ }
++}
++
++static int
++wl_closure_close_fds(struct wl_closure *closure)
++{
++ int i;
++ struct argument_details arg;
++ const char *signature = closure->message->signature;
++
++ for (i = 0; i < closure->count; i++) {
++ signature = get_next_argument(signature, &arg);
++ if (arg.type == 'h' && closure->args[i].h != -1)
++ close(closure->args[i].h);
++ }
++
++ return 0;
++}
++
++void
++wl_closure_destroy(struct wl_closure *closure)
++{
++ /* wl_closure_destroy has free() semantics */
++ if (!closure)
++ return;
++
++ wl_closure_close_fds(closure);
++ free(closure);
++}
--- /dev/null
--- /dev/null
++#!/usr/bin/env python3
++
++"""
++Simple C data embedder
++
++License: MIT
++
++Copyright (c) 2020 Simon Ser
++
++Permission is hereby granted, free of charge, to any person obtaining a copy
++of this software and associated documentation files (the "Software"), to deal
++in the Software without restriction, including without limitation the rights
++to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++copies of the Software, and to permit persons to whom the Software is
++furnished to do so, subject to the following conditions:
++
++The above copyright notice and this permission notice shall be included in all
++copies or substantial portions of the Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++SOFTWARE.
++"""
++
++import sys
++
++if len(sys.argv) != 3:
++ print('usage: ' + sys.argv[0] + ' <filename> <ident>', file=sys.stderr)
++ sys.exit(1)
++
++filename = sys.argv[1]
++ident = sys.argv[2]
++
++with open(filename, 'rb') as f:
++ buf = f.read()
++
++print('static const char ' + ident + '[] = {\n\t', end='')
++for i in range(len(buf)):
++ ch = buf[i:i+1]
++ print('0x' + ch.hex() + ', ', end='')
++print('\n};')
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++#include <stddef.h>
++#include <stdio.h>
++#include <errno.h>
++#include <signal.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <stdbool.h>
++#include <string.h>
++#include <fcntl.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <sys/epoll.h>
++#include <sys/signalfd.h>
++#include <sys/timerfd.h>
++#include <unistd.h>
++#include "wayland-util.h"
++#include "wayland-private.h"
++#include "wayland-server-core.h"
++#include "wayland-os.h"
++
++/** \cond INTERNAL */
++
++#define TIMER_REMOVED -2
++
++struct wl_event_loop;
++struct wl_event_source_interface;
++struct wl_event_source_timer;
++
++struct wl_event_source {
++ struct wl_event_source_interface *interface;
++ struct wl_event_loop *loop;
++ struct wl_list link;
++ void *data;
++ int fd;
++};
++
++struct wl_timer_heap {
++ struct wl_event_source base;
++ /* pointers to the user-visible event sources */
++ struct wl_event_source_timer **data;
++ int space, active, count;
++};
++
++struct wl_event_loop {
++ int epoll_fd;
++ struct wl_list check_list;
++ struct wl_list idle_list;
++ struct wl_list destroy_list;
++
++ struct wl_signal destroy_signal;
++
++ struct wl_timer_heap timers;
++};
++
++struct wl_event_source_interface {
++ int (*dispatch)(struct wl_event_source *source,
++ struct epoll_event *ep);
++};
++
++
++struct wl_event_source_fd {
++ struct wl_event_source base;
++ wl_event_loop_fd_func_t func;
++ int fd;
++};
++
++/** \endcond */
++
++static int
++wl_event_source_fd_dispatch(struct wl_event_source *source,
++ struct epoll_event *ep)
++{
++ struct wl_event_source_fd *fd_source = (struct wl_event_source_fd *) source;
++ uint32_t mask;
++
++ mask = 0;
++ if (ep->events & EPOLLIN)
++ mask |= WL_EVENT_READABLE;
++ if (ep->events & EPOLLOUT)
++ mask |= WL_EVENT_WRITABLE;
++ if (ep->events & EPOLLHUP)
++ mask |= WL_EVENT_HANGUP;
++ if (ep->events & EPOLLERR)
++ mask |= WL_EVENT_ERROR;
++
++ return fd_source->func(fd_source->fd, mask, source->data);
++}
++
++struct wl_event_source_interface fd_source_interface = {
++ wl_event_source_fd_dispatch,
++};
++
++static struct wl_event_source *
++add_source(struct wl_event_loop *loop,
++ struct wl_event_source *source, uint32_t mask, void *data)
++{
++ struct epoll_event ep;
++
++ if (source->fd < 0) {
++ free(source);
++ return NULL;
++ }
++
++ source->loop = loop;
++ source->data = data;
++ wl_list_init(&source->link);
++
++ memset(&ep, 0, sizeof ep);
++ if (mask & WL_EVENT_READABLE)
++ ep.events |= EPOLLIN;
++ if (mask & WL_EVENT_WRITABLE)
++ ep.events |= EPOLLOUT;
++ ep.data.ptr = source;
++
++ if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) {
++ close(source->fd);
++ free(source);
++ return NULL;
++ }
++
++ return source;
++}
++
++/** Create a file descriptor event source
++ *
++ * \param loop The event loop that will process the new source.
++ * \param fd The file descriptor to watch.
++ * \param mask A bitwise-or of which events to watch for: \c WL_EVENT_READABLE,
++ * \c WL_EVENT_WRITABLE.
++ * \param func The file descriptor dispatch function.
++ * \param data User data.
++ * \return A new file descriptor event source.
++ *
++ * The given file descriptor is initially watched for the events given in
++ * \c mask. This can be changed as needed with wl_event_source_fd_update().
++ *
++ * If it is possible that program execution causes the file descriptor to be
++ * read while leaving the data in a buffer without actually processing it,
++ * it may be necessary to register the file descriptor source to be re-checked,
++ * see wl_event_source_check(). This will ensure that the dispatch function
++ * gets called even if the file descriptor is not readable or writable
++ * anymore. This is especially useful with IPC libraries that automatically
++ * buffer incoming data, possibly as a side-effect of other operations.
++ *
++ * \sa wl_event_loop_fd_func_t
++ * \memberof wl_event_source
++ */
++WL_EXPORT struct wl_event_source *
++wl_event_loop_add_fd(struct wl_event_loop *loop,
++ int fd, uint32_t mask,
++ wl_event_loop_fd_func_t func,
++ void *data)
++{
++ struct wl_event_source_fd *source;
++
++ source = zalloc(sizeof *source);
++ if (source == NULL)
++ return NULL;
++
++ source->base.interface = &fd_source_interface;
++ source->base.fd = wl_os_dupfd_cloexec(fd, 0);
++ source->func = func;
++ source->fd = fd;
++
++ return add_source(loop, &source->base, mask, data);
++}
++
++/** Update a file descriptor source's event mask
++ *
++ * \param source The file descriptor event source to update.
++ * \param mask The new mask, a bitwise-or of: \c WL_EVENT_READABLE,
++ * \c WL_EVENT_WRITABLE.
++ * \return 0 on success, -1 on failure.
++ *
++ * This changes which events, readable and/or writable, cause the dispatch
++ * callback to be called on.
++ *
++ * File descriptors are usually writable to begin with, so they do not need to
++ * be polled for writable until a write actually fails. When a write fails,
++ * the event mask can be changed to poll for readable and writable, delivering
++ * a dispatch callback when it is possible to write more. Once all data has
++ * been written, the mask can be changed to poll only for readable to avoid
++ * busy-looping on dispatch.
++ *
++ * \sa wl_event_loop_add_fd()
++ * \memberof wl_event_source
++ */
++WL_EXPORT int
++wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask)
++{
++ struct wl_event_loop *loop = source->loop;
++ struct epoll_event ep;
++
++ memset(&ep, 0, sizeof ep);
++ if (mask & WL_EVENT_READABLE)
++ ep.events |= EPOLLIN;
++ if (mask & WL_EVENT_WRITABLE)
++ ep.events |= EPOLLOUT;
++ ep.data.ptr = source;
++
++ return epoll_ctl(loop->epoll_fd, EPOLL_CTL_MOD, source->fd, &ep);
++}
++
++/** \cond INTERNAL */
++
++struct wl_event_source_timer {
++ struct wl_event_source base;
++ wl_event_loop_timer_func_t func;
++ struct wl_event_source_timer *next_due;
++ struct timespec deadline;
++ int heap_idx;
++};
++
++static int
++noop_dispatch(struct wl_event_source *source,
++ struct epoll_event *ep) {
++ return 0;
++}
++
++struct wl_event_source_interface timer_heap_source_interface = {
++ noop_dispatch,
++};
++
++static bool
++time_lt(struct timespec ta, struct timespec tb)
++{
++ if (ta.tv_sec != tb.tv_sec) {
++ return ta.tv_sec < tb.tv_sec;
++ }
++ return ta.tv_nsec < tb.tv_nsec;
++}
++
++static int
++set_timer(int timerfd, struct timespec deadline) {
++ struct itimerspec its;
++
++ its.it_interval.tv_sec = 0;
++ its.it_interval.tv_nsec = 0;
++ its.it_value = deadline;
++ return timerfd_settime(timerfd, TFD_TIMER_ABSTIME, &its, NULL);
++}
++
++static int
++clear_timer(int timerfd)
++{
++ struct itimerspec its;
++
++ its.it_interval.tv_sec = 0;
++ its.it_interval.tv_nsec = 0;
++ its.it_value.tv_sec = 0;
++ its.it_value.tv_nsec = 0;
++ return timerfd_settime(timerfd, 0, &its, NULL);
++}
++
++static void
++wl_timer_heap_init(struct wl_timer_heap *timers, struct wl_event_loop *loop)
++{
++ timers->base.fd = -1;
++ timers->base.data = NULL;
++ wl_list_init(&timers->base.link);
++ timers->base.interface = &timer_heap_source_interface;
++ timers->base.loop = loop;
++
++ loop->timers.data = NULL;
++ loop->timers.active = 0;
++ loop->timers.space = 0;
++ loop->timers.count = 0;
++}
++
++static void
++wl_timer_heap_release(struct wl_timer_heap *timers)
++{
++ if (timers->base.fd != -1) {
++ close(timers->base.fd);
++ }
++ free(timers->data);
++}
++
++static int
++wl_timer_heap_ensure_timerfd(struct wl_timer_heap *timers)
++{
++ struct epoll_event ep;
++ int timer_fd;
++
++ if (timers->base.fd != -1)
++ return 0;
++
++ memset(&ep, 0, sizeof ep);
++ ep.events = EPOLLIN;
++ ep.data.ptr = timers;
++
++ timer_fd = timerfd_create(CLOCK_MONOTONIC,
++ TFD_CLOEXEC | TFD_NONBLOCK);
++ if (timer_fd < 0)
++ return -1;
++
++ if (epoll_ctl(timers->base.loop->epoll_fd,
++ EPOLL_CTL_ADD, timer_fd, &ep) < 0) {
++ close(timer_fd);
++ return -1;
++ }
++
++ timers->base.fd = timer_fd;
++ return 0;
++}
++
++static int
++wl_timer_heap_reserve(struct wl_timer_heap *timers)
++{
++ struct wl_event_source_timer **n;
++ int new_space;
++
++ if (timers->count + 1 > timers->space) {
++ new_space = timers->space >= 8 ? timers->space * 2 : 8;
++ n = realloc(timers->data, (size_t)new_space * sizeof(*n));
++ if (!n) {
++ wl_log("Allocation failure when expanding timer list\n");
++ return -1;
++ }
++ timers->data = n;
++ timers->space = new_space;
++ }
++
++ timers->count++;
++ return 0;
++}
++
++static void
++wl_timer_heap_unreserve(struct wl_timer_heap *timers)
++{
++ struct wl_event_source_timer **n;
++
++ timers->count--;
++
++ if (timers->space >= 16 && timers->space >= 4 * timers->count) {
++ n = realloc(timers->data, (size_t)timers->space / 2 * sizeof(*n));
++ if (!n) {
++ wl_log("Reallocation failure when shrinking timer list\n");
++ return;
++ }
++ timers->data = n;
++ timers->space = timers->space / 2;
++ }
++}
++
++static int
++heap_set(struct wl_event_source_timer **data,
++ struct wl_event_source_timer *a,
++ int idx)
++{
++ int tmp;
++
++ tmp = a->heap_idx;
++ a->heap_idx = idx;
++ data[a->heap_idx] = a;
++
++ return tmp;
++}
++
++static void
++heap_sift_down(struct wl_event_source_timer **data,
++ int num_active,
++ struct wl_event_source_timer *source)
++{
++ struct wl_event_source_timer *child, *other_child;
++ int cursor_idx;
++ struct timespec key;
++
++ cursor_idx = source->heap_idx;
++ key = source->deadline;
++ while (1) {
++ int lchild_idx = cursor_idx * 2 + 1;
++
++ if (lchild_idx >= num_active) {
++ break;
++ }
++
++ child = data[lchild_idx];
++ if (lchild_idx + 1 < num_active) {
++ other_child = data[lchild_idx + 1];
++ if (time_lt(other_child->deadline, child->deadline))
++ child = other_child;
++ }
++
++ if (time_lt(child->deadline, key))
++ cursor_idx = heap_set(data, child, cursor_idx);
++ else
++ break;
++ }
++
++ heap_set(data, source, cursor_idx);
++}
++
++static void
++heap_sift_up(struct wl_event_source_timer **data,
++ struct wl_event_source_timer *source)
++{
++ int cursor_idx;
++ struct timespec key;
++
++ cursor_idx = source->heap_idx;
++ key = source->deadline;
++ while (cursor_idx > 0) {
++ struct wl_event_source_timer *parent =
++ data[(cursor_idx - 1) / 2];
++
++ if (time_lt(key, parent->deadline))
++ cursor_idx = heap_set(data, parent, cursor_idx);
++ else
++ break;
++ }
++ heap_set(data, source, cursor_idx);
++}
++
++/* requires timer be armed */
++static void
++wl_timer_heap_disarm(struct wl_timer_heap *timers,
++ struct wl_event_source_timer *source)
++{
++ struct wl_event_source_timer *last_end_evt;
++ int old_source_idx;
++
++ assert(source->heap_idx >= 0);
++
++ old_source_idx = source->heap_idx;
++ source->heap_idx = -1;
++ source->deadline.tv_sec = 0;
++ source->deadline.tv_nsec = 0;
++
++ last_end_evt = timers->data[timers->active - 1];
++ timers->data[timers->active - 1] = NULL;
++ timers->active--;
++
++ if (old_source_idx == timers->active)
++ return;
++
++ timers->data[old_source_idx] = last_end_evt;
++ last_end_evt->heap_idx = old_source_idx;
++
++ /* Move the displaced (active) element to its proper place.
++ * Only one of sift-down and sift-up will have any effect */
++ heap_sift_down(timers->data, timers->active, last_end_evt);
++ heap_sift_up(timers->data, last_end_evt);
++}
++
++/* requires timer be disarmed */
++static void
++wl_timer_heap_arm(struct wl_timer_heap *timers,
++ struct wl_event_source_timer *source,
++ struct timespec deadline)
++{
++ assert(source->heap_idx == -1);
++
++ source->deadline = deadline;
++ timers->data[timers->active] = source;
++ source->heap_idx = timers->active;
++ timers->active++;
++ heap_sift_up(timers->data, source);
++}
++
++
++static int
++wl_timer_heap_dispatch(struct wl_timer_heap *timers)
++{
++ struct timespec now;
++ struct wl_event_source_timer *root;
++ struct wl_event_source_timer *list_cursor = NULL, *list_tail = NULL;
++
++ clock_gettime(CLOCK_MONOTONIC, &now);
++
++ while (timers->active > 0) {
++ root = timers->data[0];
++ if (time_lt(now, root->deadline))
++ break;
++
++ wl_timer_heap_disarm(timers, root);
++
++ if (list_cursor == NULL)
++ list_cursor = root;
++ else
++ list_tail->next_due = root;
++ list_tail = root;
++ }
++ if (list_tail)
++ list_tail->next_due = NULL;
++
++ if (timers->active > 0) {
++ if (set_timer(timers->base.fd, timers->data[0]->deadline) < 0)
++ return -1;
++ } else {
++ if (clear_timer(timers->base.fd) < 0)
++ return -1;
++ }
++
++ /* Execute precisely the functions for events before `now`, in order.
++ * Because wl_event_loop_dispatch ignores return codes, do the same
++ * here as well */
++ for (; list_cursor; list_cursor = list_cursor->next_due) {
++ if (list_cursor->base.fd != TIMER_REMOVED)
++ list_cursor->func(list_cursor->base.data);
++ }
++
++ return 0;
++}
++
++static int
++wl_event_source_timer_dispatch(struct wl_event_source *source,
++ struct epoll_event *ep)
++{
++ struct wl_event_source_timer *timer;
++
++ timer = wl_container_of(source, timer, base);
++ return timer->func(timer->base.data);
++}
++
++struct wl_event_source_interface timer_source_interface = {
++ wl_event_source_timer_dispatch,
++};
++
++/** \endcond */
++
++/** Create a timer event source
++ *
++ * \param loop The event loop that will process the new source.
++ * \param func The timer dispatch function.
++ * \param data User data.
++ * \return A new timer event source.
++ *
++ * The timer is initially disarmed. It needs to be armed with a call to
++ * wl_event_source_timer_update() before it can trigger a dispatch call.
++ *
++ * \sa wl_event_loop_timer_func_t
++ * \memberof wl_event_source
++ */
++WL_EXPORT struct wl_event_source *
++wl_event_loop_add_timer(struct wl_event_loop *loop,
++ wl_event_loop_timer_func_t func,
++ void *data)
++{
++ struct wl_event_source_timer *source;
++
++ if (wl_timer_heap_ensure_timerfd(&loop->timers) < 0)
++ return NULL;
++
++ source = zalloc(sizeof *source);
++ if (source == NULL)
++ return NULL;
++
++ source->base.interface = &timer_source_interface;
++ source->base.fd = -1;
++ source->func = func;
++ source->base.loop = loop;
++ source->base.data = data;
++ wl_list_init(&source->base.link);
++ source->next_due = NULL;
++ source->deadline.tv_sec = 0;
++ source->deadline.tv_nsec = 0;
++ source->heap_idx = -1;
++
++ if (wl_timer_heap_reserve(&loop->timers) < 0) {
++ free(source);
++ return NULL;
++ }
++
++ return &source->base;
++}
++
++/** Arm or disarm a timer
++ *
++ * \param source The timer event source to modify.
++ * \param ms_delay The timeout in milliseconds.
++ * \return 0 on success, -1 on failure.
++ *
++ * If the timeout is zero, the timer is disarmed.
++ *
++ * If the timeout is non-zero, the timer is set to expire after the given
++ * timeout in milliseconds. When the timer expires, the dispatch function
++ * set with wl_event_loop_add_timer() is called once from
++ * wl_event_loop_dispatch(). If another dispatch is desired after another
++ * expiry, wl_event_source_timer_update() needs to be called again.
++ *
++ * \memberof wl_event_source
++ */
++WL_EXPORT int
++wl_event_source_timer_update(struct wl_event_source *source, int ms_delay)
++{
++ struct wl_event_source_timer *tsource =
++ wl_container_of(source, tsource, base);
++ struct wl_timer_heap *timers = &tsource->base.loop->timers;
++
++ if (ms_delay > 0) {
++ struct timespec deadline;
++
++ clock_gettime(CLOCK_MONOTONIC, &deadline);
++
++ deadline.tv_nsec += (ms_delay % 1000) * 1000000L;
++ deadline.tv_sec += ms_delay / 1000;
++ if (deadline.tv_nsec >= 1000000000L) {
++ deadline.tv_nsec -= 1000000000L;
++ deadline.tv_sec += 1;
++ }
++
++ if (tsource->heap_idx == -1) {
++ wl_timer_heap_arm(timers, tsource, deadline);
++ } else if (time_lt(deadline, tsource->deadline)) {
++ tsource->deadline = deadline;
++ heap_sift_up(timers->data, tsource);
++ } else {
++ tsource->deadline = deadline;
++ heap_sift_down(timers->data, timers->active, tsource);
++ }
++
++ if (tsource->heap_idx == 0) {
++ /* Only update the timerfd if the new deadline is
++ * the earliest */
++ if (set_timer(timers->base.fd, deadline) < 0)
++ return -1;
++ }
++ } else {
++ if (tsource->heap_idx == -1)
++ return 0;
++ wl_timer_heap_disarm(timers, tsource);
++
++ if (timers->active == 0) {
++ /* Only update the timerfd if this was the last
++ * active timer */
++ if (clear_timer(timers->base.fd) < 0)
++ return -1;
++ }
++ }
++
++ return 0;
++}
++
++/** \cond INTERNAL */
++
++struct wl_event_source_signal {
++ struct wl_event_source base;
++ int signal_number;
++ wl_event_loop_signal_func_t func;
++};
++
++/** \endcond */
++
++static int
++wl_event_source_signal_dispatch(struct wl_event_source *source,
++ struct epoll_event *ep)
++{
++ struct wl_event_source_signal *signal_source =
++ (struct wl_event_source_signal *) source;
++ struct signalfd_siginfo signal_info;
++ int len;
++
++ len = read(source->fd, &signal_info, sizeof signal_info);
++ if (!(len == -1 && errno == EAGAIN) && len != sizeof signal_info)
++ /* Is there anything we can do here? Will this ever happen? */
++ wl_log("signalfd read error: %s\n", strerror(errno));
++
++ return signal_source->func(signal_source->signal_number,
++ signal_source->base.data);
++}
++
++struct wl_event_source_interface signal_source_interface = {
++ wl_event_source_signal_dispatch,
++};
++
++/** Create a POSIX signal event source
++ *
++ * \param loop The event loop that will process the new source.
++ * \param signal_number Number of the signal to watch for.
++ * \param func The signal dispatch function.
++ * \param data User data.
++ * \return A new signal event source.
++ *
++ * This function blocks the normal delivery of the given signal in the calling
++ * thread, and creates a "watch" for it. Signal delivery no longer happens
++ * asynchronously, but by wl_event_loop_dispatch() calling the dispatch
++ * callback function \c func.
++ *
++ * It is the caller's responsibility to ensure that all other threads have
++ * also blocked the signal.
++ *
++ * \sa wl_event_loop_signal_func_t
++ * \memberof wl_event_source
++ */
++WL_EXPORT struct wl_event_source *
++wl_event_loop_add_signal(struct wl_event_loop *loop,
++ int signal_number,
++ wl_event_loop_signal_func_t func,
++ void *data)
++{
++ struct wl_event_source_signal *source;
++ sigset_t mask;
++
++ source = zalloc(sizeof *source);
++ if (source == NULL)
++ return NULL;
++
++ source->base.interface = &signal_source_interface;
++ source->signal_number = signal_number;
++
++ sigemptyset(&mask);
++ sigaddset(&mask, signal_number);
++ source->base.fd = signalfd(-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK);
++ sigprocmask(SIG_BLOCK, &mask, NULL);
++
++ source->func = func;
++
++ return add_source(loop, &source->base, WL_EVENT_READABLE, data);
++}
++
++/** \cond INTERNAL */
++
++struct wl_event_source_idle {
++ struct wl_event_source base;
++ wl_event_loop_idle_func_t func;
++};
++
++/** \endcond */
++
++struct wl_event_source_interface idle_source_interface = {
++ NULL,
++};
++
++/** Create an idle task
++ *
++ * \param loop The event loop that will process the new task.
++ * \param func The idle task dispatch function.
++ * \param data User data.
++ * \return A new idle task (an event source).
++ *
++ * Idle tasks are dispatched before wl_event_loop_dispatch() goes to sleep.
++ * See wl_event_loop_dispatch() for more details.
++ *
++ * Idle tasks fire once, and are automatically destroyed right after the
++ * callback function has been called.
++ *
++ * An idle task can be cancelled before the callback has been called by
++ * wl_event_source_remove(). Calling wl_event_source_remove() after or from
++ * within the callback results in undefined behaviour.
++ *
++ * \sa wl_event_loop_idle_func_t
++ * \memberof wl_event_source
++ */
++WL_EXPORT struct wl_event_source *
++wl_event_loop_add_idle(struct wl_event_loop *loop,
++ wl_event_loop_idle_func_t func,
++ void *data)
++{
++ struct wl_event_source_idle *source;
++
++ source = zalloc(sizeof *source);
++ if (source == NULL)
++ return NULL;
++
++ source->base.interface = &idle_source_interface;
++ source->base.loop = loop;
++ source->base.fd = -1;
++
++ source->func = func;
++ source->base.data = data;
++
++ wl_list_insert(loop->idle_list.prev, &source->base.link);
++
++ return &source->base;
++}
++
++/** Mark event source to be re-checked
++ *
++ * \param source The event source to be re-checked.
++ *
++ * This function permanently marks the event source to be re-checked after
++ * the normal dispatch of sources in wl_event_loop_dispatch(). Re-checking
++ * will keep iterating over all such event sources until the dispatch
++ * function for them all returns zero.
++ *
++ * Re-checking is used on sources that may become ready to dispatch as a
++ * side-effect of dispatching themselves or other event sources, including idle
++ * sources. Re-checking ensures all the incoming events have been fully drained
++ * before wl_event_loop_dispatch() returns.
++ *
++ * \memberof wl_event_source
++ */
++WL_EXPORT void
++wl_event_source_check(struct wl_event_source *source)
++{
++ wl_list_insert(source->loop->check_list.prev, &source->link);
++}
++
++/** Remove an event source from its event loop
++ *
++ * \param source The event source to be removed.
++ * \return Zero.
++ *
++ * The event source is removed from the event loop it was created for,
++ * and is effectively destroyed. This invalidates \c source .
++ * The dispatch function of the source will no longer be called through this
++ * source.
++ *
++ * \memberof wl_event_source
++ */
++WL_EXPORT int
++wl_event_source_remove(struct wl_event_source *source)
++{
++ struct wl_event_loop *loop = source->loop;
++
++ /* We need to explicitly remove the fd, since closing the fd
++ * isn't enough in case we've dup'ed the fd. */
++ if (source->fd >= 0) {
++ epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, source->fd, NULL);
++ close(source->fd);
++ source->fd = -1;
++ }
++
++ if (source->interface == &timer_source_interface &&
++ source->fd != TIMER_REMOVED) {
++ /* Disarm the timer (and the loop's timerfd, if necessary),
++ * before removing its space in the loop timer heap */
++ wl_event_source_timer_update(source, 0);
++ wl_timer_heap_unreserve(&loop->timers);
++ /* Set the fd field to to indicate that the timer should NOT
++ * be dispatched in `wl_event_loop_dispatch` */
++ source->fd = TIMER_REMOVED;
++ }
++
++ wl_list_remove(&source->link);
++ wl_list_insert(&loop->destroy_list, &source->link);
++
++ return 0;
++}
++
++static void
++wl_event_loop_process_destroy_list(struct wl_event_loop *loop)
++{
++ struct wl_event_source *source, *next;
++
++ wl_list_for_each_safe(source, next, &loop->destroy_list, link)
++ free(source);
++
++ wl_list_init(&loop->destroy_list);
++}
++
++/** Create a new event loop context
++ *
++ * \return A new event loop context object.
++ *
++ * This creates a new event loop context. Initially this context is empty.
++ * Event sources need to be explicitly added to it.
++ *
++ * Normally the event loop is run by calling wl_event_loop_dispatch() in
++ * a loop until the program terminates. Alternatively, an event loop can be
++ * embedded in another event loop by its file descriptor, see
++ * wl_event_loop_get_fd().
++ *
++ * \memberof wl_event_loop
++ */
++WL_EXPORT struct wl_event_loop *
++wl_event_loop_create(void)
++{
++ struct wl_event_loop *loop;
++
++ loop = zalloc(sizeof *loop);
++ if (loop == NULL)
++ return NULL;
++
++ loop->epoll_fd = wl_os_epoll_create_cloexec();
++ if (loop->epoll_fd < 0) {
++ free(loop);
++ return NULL;
++ }
++ wl_list_init(&loop->check_list);
++ wl_list_init(&loop->idle_list);
++ wl_list_init(&loop->destroy_list);
++
++ wl_signal_init(&loop->destroy_signal);
++
++ wl_timer_heap_init(&loop->timers, loop);
++
++ return loop;
++}
++
++/** Destroy an event loop context
++ *
++ * \param loop The event loop to be destroyed.
++ *
++ * This emits the event loop destroy signal, closes the event loop file
++ * descriptor, and frees \c loop.
++ *
++ * If the event loop has existing sources, those cannot be safely removed
++ * afterwards. Therefore one must call wl_event_source_remove() on all
++ * event sources before destroying the event loop context.
++ *
++ * \memberof wl_event_loop
++ */
++WL_EXPORT void
++wl_event_loop_destroy(struct wl_event_loop *loop)
++{
++ wl_signal_emit(&loop->destroy_signal, loop);
++
++ wl_event_loop_process_destroy_list(loop);
++ wl_timer_heap_release(&loop->timers);
++ close(loop->epoll_fd);
++ free(loop);
++}
++
++static bool
++post_dispatch_check(struct wl_event_loop *loop)
++{
++ struct epoll_event ep;
++ struct wl_event_source *source, *next;
++ bool needs_recheck = false;
++
++ ep.events = 0;
++ wl_list_for_each_safe(source, next, &loop->check_list, link) {
++ int dispatch_result;
++
++ dispatch_result = source->interface->dispatch(source, &ep);
++ if (dispatch_result < 0) {
++ wl_log("Source dispatch function returned negative value!\n");
++ wl_log("This would previously accidentally suppress a follow-up dispatch\n");
++ }
++ needs_recheck |= dispatch_result != 0;
++ }
++
++ return needs_recheck;
++}
++
++/** Dispatch the idle sources
++ *
++ * \param loop The event loop whose idle sources are dispatched.
++ *
++ * \sa wl_event_loop_add_idle()
++ * \memberof wl_event_loop
++ */
++WL_EXPORT void
++wl_event_loop_dispatch_idle(struct wl_event_loop *loop)
++{
++ struct wl_event_source_idle *source;
++
++ while (!wl_list_empty(&loop->idle_list)) {
++ source = wl_container_of(loop->idle_list.next,
++ source, base.link);
++ source->func(source->base.data);
++ wl_event_source_remove(&source->base);
++ }
++}
++
++/** Wait for events and dispatch them
++ *
++ * \param loop The event loop whose sources to wait for.
++ * \param timeout The polling timeout in milliseconds.
++ * \return 0 for success, -1 for polling (or timer update) error.
++ *
++ * All the associated event sources are polled. This function blocks until
++ * any event source delivers an event (idle sources excluded), or the timeout
++ * expires. A timeout of -1 disables the timeout, causing the function to block
++ * indefinitely. A timeout of zero causes the poll to always return immediately.
++ *
++ * All idle sources are dispatched before blocking. An idle source is destroyed
++ * when it is dispatched. After blocking, all other ready sources are
++ * dispatched. Then, idle sources are dispatched again, in case the dispatched
++ * events created idle sources. Finally, all sources marked with
++ * wl_event_source_check() are dispatched in a loop until their dispatch
++ * functions all return zero.
++ *
++ * \memberof wl_event_loop
++ */
++WL_EXPORT int
++wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout)
++{
++ struct epoll_event ep[32];
++ struct wl_event_source *source;
++ int i, count;
++ bool has_timers = false;
++
++ wl_event_loop_dispatch_idle(loop);
++
++ count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
++ if (count < 0)
++ return -1;
++
++ for (i = 0; i < count; i++) {
++ source = ep[i].data.ptr;
++ if (source == &loop->timers.base)
++ has_timers = true;
++ }
++
++ if (has_timers) {
++ /* Dispatch timer sources before non-timer sources, so that
++ * the non-timer sources can not cancel (by calling
++ * `wl_event_source_timer_update`) the dispatching of the timers
++ * (Note that timer sources also can't cancel pending non-timer
++ * sources, since epoll_wait has already been called) */
++ if (wl_timer_heap_dispatch(&loop->timers) < 0)
++ return -1;
++ }
++
++ for (i = 0; i < count; i++) {
++ source = ep[i].data.ptr;
++ if (source->fd != -1)
++ source->interface->dispatch(source, &ep[i]);
++ }
++
++ wl_event_loop_process_destroy_list(loop);
++
++ wl_event_loop_dispatch_idle(loop);
++
++ while (post_dispatch_check(loop));
++
++ return 0;
++}
++
++/** Get the event loop file descriptor
++ *
++ * \param loop The event loop context.
++ * \return The aggregate file descriptor.
++ *
++ * This function returns the aggregate file descriptor, that represents all
++ * the event sources (idle sources excluded) associated with the given event
++ * loop context. When any event source makes an event available, it will be
++ * reflected in the aggregate file descriptor.
++ *
++ * When the aggregate file descriptor delivers an event, one can call
++ * wl_event_loop_dispatch() on the event loop context to dispatch all the
++ * available events.
++ *
++ * \memberof wl_event_loop
++ */
++WL_EXPORT int
++wl_event_loop_get_fd(struct wl_event_loop *loop)
++{
++ return loop->epoll_fd;
++}
++
++/** Register a destroy listener for an event loop context
++ *
++ * \param loop The event loop context whose destruction to listen for.
++ * \param listener The listener with the callback to be called.
++ *
++ * \sa wl_listener
++ * \memberof wl_event_loop
++ */
++WL_EXPORT void
++wl_event_loop_add_destroy_listener(struct wl_event_loop *loop,
++ struct wl_listener *listener)
++{
++ wl_signal_add(&loop->destroy_signal, listener);
++}
++
++/** Get the listener struct for the specified callback
++ *
++ * \param loop The event loop context to inspect.
++ * \param notify The destroy callback to find.
++ * \return The wl_listener registered to the event loop context with
++ * the given callback pointer.
++ *
++ * \memberof wl_event_loop
++ */
++WL_EXPORT struct wl_listener *
++wl_event_loop_get_destroy_listener(struct wl_event_loop *loop,
++ wl_notify_func_t notify)
++{
++ return wl_signal_get(&loop->destroy_signal, notify);
++}
--- /dev/null
--- /dev/null
++if not (get_option('scanner') or get_option('libraries'))
++ error('Either -Dscanner=true or -Dlibraries=true is required')
++endif
++
++wayland_version_h = configuration_data()
++wayland_version_h.set('WAYLAND_VERSION', meson.project_version())
++wayland_version_h.set('WAYLAND_VERSION_MAJOR', wayland_version[0].to_int())
++wayland_version_h.set('WAYLAND_VERSION_MINOR', wayland_version[1].to_int())
++wayland_version_h.set('WAYLAND_VERSION_MICRO', wayland_version[2].to_int())
++configure_file(
++ input: 'wayland-version.h.in',
++ output: 'wayland-version.h',
++ configuration: wayland_version_h,
++ install: get_option('libraries'),
++ install_dir: join_paths(get_option('prefix'), get_option('includedir'))
++)
++
++
++wayland_util = static_library(
++ 'wayland-util',
++ sources: 'wayland-util.c'
++)
++
++wayland_util_dep = declare_dependency(
++ link_with: wayland_util,
++ include_directories: include_directories('.')
++)
++
++if get_option('scanner')
++ # wayland-scanner
++
++ scanner_deps = [ dependency('expat') ]
++ scanner_args = [ '-include', 'config.h' ]
++
++ if get_option('dtd_validation')
++ scanner_deps += dependency('libxml-2.0')
++ scanner_args += '-DHAVE_LIBXML=1'
++ endif
++
++ prog_embed = find_program('embed.py', native: true)
++
++ embed_dtd = custom_target(
++ 'wayland.dtd.h',
++ input: '../protocol/wayland.dtd',
++ output: 'wayland.dtd.h',
++ command: [ prog_embed, '@INPUT@', 'wayland_dtd' ],
++ capture: true
++ )
++
++ wayland_scanner_sources = [ 'scanner.c', embed_dtd ]
++ wayland_scanner_includes = [ root_inc, protocol_inc ]
++
++ wayland_scanner = executable(
++ 'wayland-scanner',
++ wayland_scanner_sources,
++ c_args: scanner_args,
++ include_directories: wayland_scanner_includes,
++ dependencies: [ scanner_deps, wayland_util_dep, ],
++ install: true
++ )
++
++ pkgconfig.generate(
++ name: 'Wayland Scanner',
++ description: 'Wayland scanner',
++ version: meson.project_version(),
++ variables: [
++ 'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
++ 'pkgdatadir=' + join_paths('${datarootdir}', meson.project_name()),
++ 'bindir=' + join_paths('${prefix}', get_option('bindir')),
++ 'wayland_scanner=${bindir}/wayland-scanner'
++ ],
++ filebase: 'wayland-scanner'
++ )
++
++ if meson.can_run_host_binaries()
++ meson.override_find_program('wayland-scanner', wayland_scanner)
++ endif
++endif
++
++if meson.is_cross_build() or not get_option('scanner')
++ scanner_dep = dependency('wayland-scanner', native: true, version: meson.project_version())
++ wayland_scanner_for_build = find_program(scanner_dep.get_variable(pkgconfig: 'wayland_scanner'))
++else
++ wayland_scanner_for_build = wayland_scanner
++endif
++
++if get_option('libraries')
++ # wayland libraries
++
++ mathlib_dep = cc.find_library('m', required: false)
++ threads_dep = dependency('threads', required: false)
++
++ wayland_private = static_library(
++ 'wayland-private',
++ sources: [
++ 'connection.c',
++ 'wayland-os.c'
++ ],
++ dependencies: [ epoll_dep, ffi_dep, rt_dep ]
++ )
++
++ wayland_private_dep = declare_dependency(
++ link_with: wayland_private,
++ include_directories: include_directories('.')
++ )
++
++ generated_headers = [
++ {
++ 'scanner_args': ['server-header'],
++ 'output': 'wayland-server-protocol.h',
++ 'install': true,
++ },
++ {
++ 'scanner_args': ['server-header', '-c'],
++ 'output': 'wayland-server-protocol-core.h',
++ 'install': false,
++ },
++ {
++ 'scanner_args': ['client-header'],
++ 'output': 'wayland-client-protocol.h',
++ 'install': true,
++ },
++ {
++ 'scanner_args': ['client-header', '-c'],
++ 'output': 'wayland-client-protocol-core.h',
++ 'install': false,
++ },
++ ]
++
++ foreach gen: generated_headers
++ scanner_args = gen['scanner_args']
++ output_file = gen['output']
++ install_file = gen['install']
++ install_dir = join_paths(get_option('prefix'), get_option('includedir'))
++ target_name = output_file.underscorify()
++
++ target = custom_target(
++ target_name,
++ command: [
++ wayland_scanner_for_build, '-s', scanner_args,
++ '@INPUT@', '@OUTPUT@'
++ ],
++ input: wayland_protocol_xml,
++ output: output_file,
++ install: install_file,
++ install_dir: install_dir
++ )
++
++ set_variable(target_name, target)
++ endforeach
++
++ wayland_protocol_c = custom_target(
++ 'protocol source',
++ command: [
++ wayland_scanner_for_build, '-s', 'public-code', '@INPUT@', '@OUTPUT@'
++ ],
++ input: wayland_protocol_xml,
++ output: 'wayland-protocol.c'
++ )
++
++ if wayland_version[0] != '1'
++ # The versioning used for the shared libraries assumes that the major
++ # version of Wayland as a whole will increase to 2 if and only if there
++ # is an ABI break, at which point we should probably bump the SONAME of
++ # all libraries to .so.2. For more details see
++ # https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/177
++ error('We probably need to bump the SONAME of libwayland-server and -client')
++ endif
++
++ wayland_server = library(
++ 'wayland-server',
++ sources: [
++ wayland_server_protocol_core_h,
++ wayland_server_protocol_h,
++ wayland_protocol_c,
++ 'wayland-server.c',
++ 'wayland-shm.c',
++ 'event-loop.c'
++ ],
++ # To avoid an unnecessary SONAME bump, wayland 1.x.y produces
++ # libwayland-server.so.0.x.y.
++ version: '.'.join(['0', wayland_version[1], wayland_version[2]]),
++ dependencies: [
++ epoll_dep,
++ ffi_dep,
++ wayland_private_dep,
++ wayland_util_dep,
++ mathlib_dep,
++ threads_dep,
++ rt_dep
++ ],
++ include_directories: root_inc,
++ install: true
++ )
++
++ wayland_server_dep = declare_dependency(
++ link_with: wayland_server,
++ include_directories: [ root_inc, include_directories('.') ],
++ dependencies: [ epoll_dep, ffi_dep, mathlib_dep, threads_dep ],
++ sources: [
++ wayland_server_protocol_core_h,
++ wayland_server_protocol_h
++ ]
++ )
++
++ pkgconfig.generate(
++ wayland_server,
++ name: 'Wayland Server',
++ description: 'Server side implementation of the Wayland protocol',
++ version: meson.project_version(),
++ filebase: 'wayland-server',
++ variables: [
++ 'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
++ 'pkgdatadir=' + join_paths('${datarootdir}', meson.project_name())
++ ]
++ )
++
++ if meson.version().version_compare('>= 0.54.0')
++ meson.override_dependency('wayland-server', wayland_server_dep)
++ endif
++
++ wayland_client = library(
++ 'wayland-client',
++ sources: [
++ wayland_client_protocol_core_h,
++ wayland_client_protocol_h,
++ wayland_protocol_c,
++ 'wayland-client.c'
++ ],
++ # To avoid an unnecessary SONAME bump, wayland 1.x.y produces
++ # libwayland-client.so.0.x.y.
++ version: '.'.join(['0', wayland_version[1], wayland_version[2]]),
++ dependencies: [
++ epoll_dep,
++ ffi_dep,
++ wayland_private_dep,
++ wayland_util_dep,
++ mathlib_dep,
++ threads_dep
++ ],
++ include_directories: root_inc,
++ install: true
++ )
++
++ pkgconfig.generate(
++ wayland_client,
++ name: 'Wayland Client',
++ description: 'Wayland client side library',
++ version: meson.project_version(),
++ filebase: 'wayland-client',
++ variables: [
++ 'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
++ 'pkgdatadir=' + join_paths('${datarootdir}', meson.project_name())
++ ]
++ )
++
++ wayland_client_dep = declare_dependency(
++ link_with: wayland_client,
++ include_directories: [ root_inc, include_directories('.') ],
++ sources: [
++ wayland_client_protocol_core_h,
++ wayland_client_protocol_h
++ ]
++ )
++
++ if meson.version().version_compare('>= 0.54.0')
++ meson.override_dependency('wayland-client', wayland_client_dep)
++ endif
++
++ install_headers([
++ 'wayland-util.h',
++ 'wayland-server.h',
++ 'wayland-server-core.h',
++ 'wayland-client.h',
++ 'wayland-client-core.h',
++ ])
++endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2011 Intel Corporation
++ * Copyright © 2015 Red Hat, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "wayland-version.h"
++
++#include <stdbool.h>
++#include <stdio.h>
++#include <stdarg.h>
++#include <stdint.h>
++#include <string.h>
++#include <errno.h>
++#include <ctype.h>
++#include <getopt.h>
++#include <limits.h>
++#include <unistd.h>
++
++#if HAVE_LIBXML
++#include <libxml/parser.h>
++
++/* Embedded wayland.dtd file */
++/* static const char wayland_dtd[]; wayland.dtd */
++#include "wayland.dtd.h"
++#endif
++
++/* Expat must be included after libxml as both want to declare XMLCALL; see
++ * the Git commit that 'git blame' for this comment points to for more. */
++#include <expat.h>
++
++#include "wayland-util.h"
++
++#define PROGRAM_NAME "wayland-scanner"
++
++enum side {
++ CLIENT,
++ SERVER,
++};
++
++enum visibility {
++ PRIVATE,
++ PUBLIC,
++};
++
++static int
++usage(int ret)
++{
++ fprintf(stderr, "usage: %s [OPTION] [client-header|server-header|private-code|public-code]"
++ " [input_file output_file]\n", PROGRAM_NAME);
++ fprintf(stderr, "\n");
++ fprintf(stderr, "Converts XML protocol descriptions supplied on "
++ "stdin or input file to client\n"
++ "headers, server headers, or protocol marshalling code.\n\n"
++ "Use \"public-code\" only if the marshalling code will be public - "
++ "aka DSO will export it while other components will be using it.\n"
++ "Using \"private-code\" is strongly recommended.\n\n");
++ fprintf(stderr, "options:\n");
++ fprintf(stderr, " -h, --help display this help and exit.\n"
++ " -v, --version print the wayland library version that\n"
++ " the scanner was built against.\n"
++ " -c, --include-core-only include the core version of the headers,\n"
++ " that is e.g. wayland-client-core.h instead\n"
++ " of wayland-client.h.\n"
++ " -s, --strict exit immediately with an error if DTD\n"
++ " verification fails.\n");
++ exit(ret);
++}
++
++static int
++scanner_version(int ret)
++{
++ fprintf(stderr, "%s %s\n", PROGRAM_NAME, WAYLAND_VERSION);
++ exit(ret);
++}
++
++static bool
++is_dtd_valid(FILE *input, const char *filename)
++{
++ bool rc = true;
++#if HAVE_LIBXML
++ xmlParserCtxtPtr ctx = NULL;
++ xmlDocPtr doc = NULL;
++ xmlDtdPtr dtd = NULL;
++ xmlValidCtxtPtr dtdctx;
++ xmlParserInputBufferPtr buffer;
++ int fd = fileno(input);
++
++ dtdctx = xmlNewValidCtxt();
++ ctx = xmlNewParserCtxt();
++ if (!ctx || !dtdctx)
++ abort();
++
++ buffer = xmlParserInputBufferCreateMem(wayland_dtd,
++ sizeof(wayland_dtd),
++ XML_CHAR_ENCODING_UTF8);
++ if (!buffer) {
++ fprintf(stderr, "Failed to init buffer for DTD.\n");
++ abort();
++ }
++
++ dtd = xmlIOParseDTD(NULL, buffer, XML_CHAR_ENCODING_UTF8);
++ if (!dtd) {
++ fprintf(stderr, "Failed to parse DTD.\n");
++ abort();
++ }
++
++ doc = xmlCtxtReadFd(ctx, fd, filename, NULL, 0);
++ if (!doc) {
++ fprintf(stderr, "Failed to read XML\n");
++ abort();
++ }
++
++ rc = xmlValidateDtd(dtdctx, doc, dtd);
++ xmlFreeDoc(doc);
++ xmlFreeParserCtxt(ctx);
++ xmlFreeDtd(dtd);
++ xmlFreeValidCtxt(dtdctx);
++ /* xmlIOParseDTD consumes buffer */
++
++ if (lseek(fd, 0, SEEK_SET) != 0) {
++ fprintf(stderr, "Failed to reset fd, output would be garbage.\n");
++ abort();
++ }
++#endif
++ return rc;
++}
++
++#define XML_BUFFER_SIZE 4096
++
++struct location {
++ const char *filename;
++ int line_number;
++};
++
++struct description {
++ char *summary;
++ char *text;
++};
++
++struct protocol {
++ char *name;
++ char *uppercase_name;
++ struct wl_list interface_list;
++ int type_index;
++ int null_run_length;
++ char *copyright;
++ struct description *description;
++ bool core_headers;
++};
++
++struct interface {
++ struct location loc;
++ char *name;
++ char *uppercase_name;
++ int version;
++ int since;
++ struct wl_list request_list;
++ struct wl_list event_list;
++ struct wl_list enumeration_list;
++ struct wl_list link;
++ struct description *description;
++};
++
++struct message {
++ struct location loc;
++ char *name;
++ char *uppercase_name;
++ struct wl_list arg_list;
++ struct wl_list link;
++ int arg_count;
++ int new_id_count;
++ int type_index;
++ int all_null;
++ int destructor;
++ int since;
++ struct description *description;
++};
++
++enum arg_type {
++ NEW_ID,
++ INT,
++ UNSIGNED,
++ FIXED,
++ STRING,
++ OBJECT,
++ ARRAY,
++ FD
++};
++
++struct arg {
++ char *name;
++ enum arg_type type;
++ int nullable;
++ char *interface_name;
++ struct wl_list link;
++ char *summary;
++ char *enumeration_name;
++};
++
++struct enumeration {
++ char *name;
++ char *uppercase_name;
++ struct wl_list entry_list;
++ struct wl_list link;
++ struct description *description;
++ bool bitfield;
++ int since;
++};
++
++struct entry {
++ char *name;
++ char *uppercase_name;
++ char *value;
++ char *summary;
++ int since;
++ struct wl_list link;
++ struct description *description;
++};
++
++struct parse_context {
++ struct location loc;
++ XML_Parser parser;
++ struct protocol *protocol;
++ struct interface *interface;
++ struct message *message;
++ struct enumeration *enumeration;
++ struct entry *entry;
++ struct description *description;
++ char character_data[8192];
++ unsigned int character_data_length;
++};
++
++enum identifier_role {
++ STANDALONE_IDENT,
++ TRAILING_IDENT
++};
++
++static void *
++fail_on_null(void *p)
++{
++ if (p == NULL) {
++ fprintf(stderr, "%s: out of memory\n", PROGRAM_NAME);
++ exit(EXIT_FAILURE);
++ }
++
++ return p;
++}
++
++static void *
++zalloc(size_t s)
++{
++ return calloc(s, 1);
++}
++
++static void *
++xzalloc(size_t s)
++{
++ return fail_on_null(zalloc(s));
++}
++
++static char *
++xstrdup(const char *s)
++{
++ return fail_on_null(strdup(s));
++}
++
++static char *
++uppercase_dup(const char *src)
++{
++ char *u;
++ int i;
++
++ u = xstrdup(src);
++ for (i = 0; u[i]; i++)
++ u[i] = toupper(u[i]);
++ u[i] = '\0';
++
++ return u;
++}
++
++static const char *indent(int n)
++{
++ const char *whitespace[] = {
++ "\t\t\t\t\t\t\t\t\t\t\t\t",
++ "\t\t\t\t\t\t\t\t\t\t\t\t ",
++ "\t\t\t\t\t\t\t\t\t\t\t\t ",
++ "\t\t\t\t\t\t\t\t\t\t\t\t ",
++ "\t\t\t\t\t\t\t\t\t\t\t\t ",
++ "\t\t\t\t\t\t\t\t\t\t\t\t ",
++ "\t\t\t\t\t\t\t\t\t\t\t\t ",
++ "\t\t\t\t\t\t\t\t\t\t\t\t "
++ };
++
++ return whitespace[n % 8] + 12 - n / 8;
++}
++
++static void
++desc_dump(char *desc, const char *fmt, ...) WL_PRINTF(2, 3);
++
++static void
++desc_dump(char *desc, const char *fmt, ...)
++{
++ va_list ap;
++ char buf[128], hang;
++ int col, i, j, k, startcol, newlines;
++
++ va_start(ap, fmt);
++ vsnprintf(buf, sizeof buf, fmt, ap);
++ va_end(ap);
++
++ for (i = 0, col = 0; buf[i] != '*'; i++) {
++ if (buf[i] == '\t')
++ col = (col + 8) & ~7;
++ else
++ col++;
++ }
++
++ printf("%s", buf);
++
++ if (!desc) {
++ printf("(none)\n");
++ return;
++ }
++
++ startcol = col;
++ col += strlen(&buf[i]);
++ if (col - startcol > 2)
++ hang = '\t';
++ else
++ hang = ' ';
++
++ for (i = 0; desc[i]; ) {
++ k = i;
++ newlines = 0;
++ while (desc[i] && isspace(desc[i])) {
++ if (desc[i] == '\n')
++ newlines++;
++ i++;
++ }
++ if (!desc[i])
++ break;
++
++ j = i;
++ while (desc[i] && !isspace(desc[i]))
++ i++;
++
++ if (newlines > 1)
++ printf("\n%s*", indent(startcol));
++ if (newlines > 1 || col + i - j > 72) {
++ printf("\n%s*%c", indent(startcol), hang);
++ col = startcol;
++ }
++
++ if (col > startcol && k > 0)
++ col += printf(" ");
++ col += printf("%.*s", i - j, &desc[j]);
++ }
++ putchar('\n');
++}
++
++static void __attribute__ ((noreturn))
++fail(struct location *loc, const char *msg, ...)
++{
++ va_list ap;
++
++ va_start(ap, msg);
++ fprintf(stderr, "%s:%d: error: ",
++ loc->filename, loc->line_number);
++ vfprintf(stderr, msg, ap);
++ fprintf(stderr, "\n");
++ va_end(ap);
++ exit(EXIT_FAILURE);
++}
++
++static void
++warn(struct location *loc, const char *msg, ...)
++{
++ va_list ap;
++
++ va_start(ap, msg);
++ fprintf(stderr, "%s:%d: warning: ",
++ loc->filename, loc->line_number);
++ vfprintf(stderr, msg, ap);
++ fprintf(stderr, "\n");
++ va_end(ap);
++}
++
++static bool
++is_nullable_type(struct arg *arg)
++{
++ switch (arg->type) {
++ /* Strings and objects are possibly nullable */
++ case STRING:
++ case OBJECT:
++ return true;
++ default:
++ return false;
++ }
++}
++
++static struct message *
++create_message(struct location loc, const char *name)
++{
++ struct message *message;
++
++ message = xzalloc(sizeof *message);
++ message->loc = loc;
++ message->name = xstrdup(name);
++ message->uppercase_name = uppercase_dup(name);
++ wl_list_init(&message->arg_list);
++
++ return message;
++}
++
++static void
++free_arg(struct arg *arg)
++{
++ free(arg->name);
++ free(arg->interface_name);
++ free(arg->summary);
++ free(arg->enumeration_name);
++ free(arg);
++}
++
++static struct arg *
++create_arg(const char *name)
++{
++ struct arg *arg;
++
++ arg = xzalloc(sizeof *arg);
++ arg->name = xstrdup(name);
++
++ return arg;
++}
++
++static bool
++set_arg_type(struct arg *arg, const char *type)
++{
++ if (strcmp(type, "int") == 0)
++ arg->type = INT;
++ else if (strcmp(type, "uint") == 0)
++ arg->type = UNSIGNED;
++ else if (strcmp(type, "fixed") == 0)
++ arg->type = FIXED;
++ else if (strcmp(type, "string") == 0)
++ arg->type = STRING;
++ else if (strcmp(type, "array") == 0)
++ arg->type = ARRAY;
++ else if (strcmp(type, "fd") == 0)
++ arg->type = FD;
++ else if (strcmp(type, "new_id") == 0)
++ arg->type = NEW_ID;
++ else if (strcmp(type, "object") == 0)
++ arg->type = OBJECT;
++ else
++ return false;
++
++ return true;
++}
++
++static void
++free_description(struct description *desc)
++{
++ if (!desc)
++ return;
++
++ free(desc->summary);
++ free(desc->text);
++
++ free(desc);
++}
++
++static void
++free_message(struct message *message)
++{
++ struct arg *a, *a_next;
++
++ free(message->name);
++ free(message->uppercase_name);
++ free_description(message->description);
++
++ wl_list_for_each_safe(a, a_next, &message->arg_list, link)
++ free_arg(a);
++
++ free(message);
++}
++
++static struct enumeration *
++create_enumeration(const char *name)
++{
++ struct enumeration *enumeration;
++
++ enumeration = xzalloc(sizeof *enumeration);
++ enumeration->name = xstrdup(name);
++ enumeration->uppercase_name = uppercase_dup(name);
++ enumeration->since = 1;
++
++ wl_list_init(&enumeration->entry_list);
++
++ return enumeration;
++}
++
++static struct entry *
++create_entry(const char *name, const char *value)
++{
++ struct entry *entry;
++
++ entry = xzalloc(sizeof *entry);
++ entry->name = xstrdup(name);
++ entry->uppercase_name = uppercase_dup(name);
++ entry->value = xstrdup(value);
++
++ return entry;
++}
++
++static void
++free_entry(struct entry *entry)
++{
++ free(entry->name);
++ free(entry->uppercase_name);
++ free(entry->value);
++ free(entry->summary);
++ free_description(entry->description);
++
++ free(entry);
++}
++
++static void
++free_enumeration(struct enumeration *enumeration)
++{
++ struct entry *e, *e_next;
++
++ free(enumeration->name);
++ free(enumeration->uppercase_name);
++ free_description(enumeration->description);
++
++ wl_list_for_each_safe(e, e_next, &enumeration->entry_list, link)
++ free_entry(e);
++
++ free(enumeration);
++}
++
++static struct interface *
++create_interface(struct location loc, const char *name, int version)
++{
++ struct interface *interface;
++
++ interface = xzalloc(sizeof *interface);
++ interface->loc = loc;
++ interface->name = xstrdup(name);
++ interface->uppercase_name = uppercase_dup(name);
++ interface->version = version;
++ interface->since = 1;
++ wl_list_init(&interface->request_list);
++ wl_list_init(&interface->event_list);
++ wl_list_init(&interface->enumeration_list);
++
++ return interface;
++}
++
++static void
++free_interface(struct interface *interface)
++{
++ struct message *m, *next_m;
++ struct enumeration *e, *next_e;
++
++ free(interface->name);
++ free(interface->uppercase_name);
++ free_description(interface->description);
++
++ wl_list_for_each_safe(m, next_m, &interface->request_list, link)
++ free_message(m);
++ wl_list_for_each_safe(m, next_m, &interface->event_list, link)
++ free_message(m);
++ wl_list_for_each_safe(e, next_e, &interface->enumeration_list, link)
++ free_enumeration(e);
++
++ free(interface);
++}
++
++/* Convert string to unsigned integer
++ *
++ * Parses a non-negative base-10 number from the given string. If the
++ * specified string is blank, contains non-numerical characters, is out
++ * of range, or results in a negative number, -1 is returned to indicate
++ * an error.
++ *
++ * Upon error, this routine does not modify or set errno.
++ *
++ * Returns -1 on error, or a non-negative integer on success
++ */
++static int
++strtouint(const char *str)
++{
++ long int ret;
++ char *end;
++ int prev_errno = errno;
++
++ errno = 0;
++ ret = strtol(str, &end, 10);
++ if (errno != 0 || end == str || *end != '\0')
++ return -1;
++
++ /* check range */
++ if (ret < 0 || ret > INT_MAX) {
++ return -1;
++ }
++
++ errno = prev_errno;
++ return (int)ret;
++}
++
++/* Check that the provided string will produce valid "C" identifiers.
++ *
++ * If the string will form the prefix of an identifier in the
++ * generated C code, then it must match [_a-zA-Z][_0-9a-zA-Z]*.
++ *
++ * If the string will form the suffix of an identifier, then
++ * it must match [_0-9a-zA-Z]+.
++ *
++ * Unicode characters or escape sequences are not permitted,
++ * since not all C compilers support them.
++ *
++ * If the above conditions are not met, then fail()
++ */
++static void
++validate_identifier(struct location *loc,
++ const char *str,
++ enum identifier_role role)
++{
++ const char *scan;
++
++ if (!*str) {
++ fail(loc, "element name is empty");
++ }
++
++ for (scan = str; *scan; scan++) {
++ char c = *scan;
++
++ /* we do not use the locale-dependent `isalpha` */
++ bool is_alpha = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
++ bool is_digit = c >= '0' && c <= '9';
++ bool leading_char = (scan == str) && role == STANDALONE_IDENT;
++
++ if (is_alpha || c == '_' || (!leading_char && is_digit))
++ continue;
++
++ if (role == TRAILING_IDENT)
++ fail(loc,
++ "'%s' is not a valid trailing identifier part", str);
++ else
++ fail(loc,
++ "'%s' is not a valid standalone identifier", str);
++ }
++}
++
++static int
++version_from_since(struct parse_context *ctx, const char *since)
++{
++ int version;
++
++ if (since != NULL) {
++ version = strtouint(since);
++ if (version == -1) {
++ fail(&ctx->loc, "invalid integer (%s)\n", since);
++ } else if (version > ctx->interface->version) {
++ fail(&ctx->loc, "since (%u) larger than version (%u)\n",
++ version, ctx->interface->version);
++ }
++ } else {
++ version = 1;
++ }
++
++
++ return version;
++}
++
++static void
++start_element(void *data, const char *element_name, const char **atts)
++{
++ struct parse_context *ctx = data;
++ struct interface *interface;
++ struct message *message;
++ struct arg *arg;
++ struct enumeration *enumeration;
++ struct entry *entry;
++ struct description *description = NULL;
++ const char *name = NULL;
++ const char *type = NULL;
++ const char *interface_name = NULL;
++ const char *value = NULL;
++ const char *summary = NULL;
++ const char *since = NULL;
++ const char *allow_null = NULL;
++ const char *enumeration_name = NULL;
++ const char *bitfield = NULL;
++ int i, version = 0;
++
++ ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser);
++ for (i = 0; atts[i]; i += 2) {
++ if (strcmp(atts[i], "name") == 0)
++ name = atts[i + 1];
++ if (strcmp(atts[i], "version") == 0) {
++ version = strtouint(atts[i + 1]);
++ if (version == -1)
++ fail(&ctx->loc, "wrong version (%s)", atts[i + 1]);
++ }
++ if (strcmp(atts[i], "type") == 0)
++ type = atts[i + 1];
++ if (strcmp(atts[i], "value") == 0)
++ value = atts[i + 1];
++ if (strcmp(atts[i], "interface") == 0)
++ interface_name = atts[i + 1];
++ if (strcmp(atts[i], "summary") == 0)
++ summary = atts[i + 1];
++ if (strcmp(atts[i], "since") == 0)
++ since = atts[i + 1];
++ if (strcmp(atts[i], "allow-null") == 0)
++ allow_null = atts[i + 1];
++ if (strcmp(atts[i], "enum") == 0)
++ enumeration_name = atts[i + 1];
++ if (strcmp(atts[i], "bitfield") == 0)
++ bitfield = atts[i + 1];
++ }
++
++ ctx->character_data_length = 0;
++ if (strcmp(element_name, "protocol") == 0) {
++ if (name == NULL)
++ fail(&ctx->loc, "no protocol name given");
++
++ validate_identifier(&ctx->loc, name, STANDALONE_IDENT);
++ ctx->protocol->name = xstrdup(name);
++ ctx->protocol->uppercase_name = uppercase_dup(name);
++ } else if (strcmp(element_name, "copyright") == 0) {
++
++ } else if (strcmp(element_name, "interface") == 0) {
++ if (name == NULL)
++ fail(&ctx->loc, "no interface name given");
++
++ if (version == 0)
++ fail(&ctx->loc, "no interface version given");
++
++ validate_identifier(&ctx->loc, name, STANDALONE_IDENT);
++ interface = create_interface(ctx->loc, name, version);
++ ctx->interface = interface;
++ wl_list_insert(ctx->protocol->interface_list.prev,
++ &interface->link);
++ } else if (strcmp(element_name, "request") == 0 ||
++ strcmp(element_name, "event") == 0) {
++ if (name == NULL)
++ fail(&ctx->loc, "no request name given");
++
++ validate_identifier(&ctx->loc, name, STANDALONE_IDENT);
++ message = create_message(ctx->loc, name);
++
++ if (strcmp(element_name, "request") == 0)
++ wl_list_insert(ctx->interface->request_list.prev,
++ &message->link);
++ else
++ wl_list_insert(ctx->interface->event_list.prev,
++ &message->link);
++
++ if (type != NULL && strcmp(type, "destructor") == 0)
++ message->destructor = 1;
++
++ version = version_from_since(ctx, since);
++
++ if (version < ctx->interface->since)
++ warn(&ctx->loc, "since version not increasing\n");
++ ctx->interface->since = version;
++ message->since = version;
++
++ if (strcmp(name, "destroy") == 0 && !message->destructor)
++ fail(&ctx->loc, "destroy request should be destructor type");
++
++ ctx->message = message;
++ } else if (strcmp(element_name, "arg") == 0) {
++ if (name == NULL)
++ fail(&ctx->loc, "no argument name given");
++
++ validate_identifier(&ctx->loc, name, STANDALONE_IDENT);
++ arg = create_arg(name);
++ if (!set_arg_type(arg, type))
++ fail(&ctx->loc, "unknown type (%s)", type);
++
++ switch (arg->type) {
++ case NEW_ID:
++ ctx->message->new_id_count++;
++ /* fallthrough */
++ case OBJECT:
++ if (interface_name) {
++ validate_identifier(&ctx->loc,
++ interface_name,
++ STANDALONE_IDENT);
++ arg->interface_name = xstrdup(interface_name);
++ }
++ break;
++ default:
++ if (interface_name != NULL)
++ fail(&ctx->loc, "interface attribute not allowed for type %s", type);
++ break;
++ }
++
++ if (allow_null) {
++ if (strcmp(allow_null, "true") == 0)
++ arg->nullable = 1;
++ else if (strcmp(allow_null, "false") != 0)
++ fail(&ctx->loc,
++ "invalid value for allow-null attribute (%s)",
++ allow_null);
++
++ if (!is_nullable_type(arg))
++ fail(&ctx->loc,
++ "allow-null is only valid for objects, strings, and arrays");
++ }
++
++ if (enumeration_name == NULL || strcmp(enumeration_name, "") == 0)
++ arg->enumeration_name = NULL;
++ else
++ arg->enumeration_name = xstrdup(enumeration_name);
++
++ if (summary)
++ arg->summary = xstrdup(summary);
++
++ wl_list_insert(ctx->message->arg_list.prev, &arg->link);
++ ctx->message->arg_count++;
++ } else if (strcmp(element_name, "enum") == 0) {
++ if (name == NULL)
++ fail(&ctx->loc, "no enum name given");
++
++ validate_identifier(&ctx->loc, name, TRAILING_IDENT);
++ enumeration = create_enumeration(name);
++
++ if (bitfield == NULL || strcmp(bitfield, "false") == 0)
++ enumeration->bitfield = false;
++ else if (strcmp(bitfield, "true") == 0)
++ enumeration->bitfield = true;
++ else
++ fail(&ctx->loc,
++ "invalid value (%s) for bitfield attribute (only true/false are accepted)",
++ bitfield);
++
++ wl_list_insert(ctx->interface->enumeration_list.prev,
++ &enumeration->link);
++
++ ctx->enumeration = enumeration;
++ } else if (strcmp(element_name, "entry") == 0) {
++ if (name == NULL)
++ fail(&ctx->loc, "no entry name given");
++
++ validate_identifier(&ctx->loc, name, TRAILING_IDENT);
++ entry = create_entry(name, value);
++ version = version_from_since(ctx, since);
++
++ if (version < ctx->enumeration->since)
++ warn(&ctx->loc, "since version not increasing\n");
++ ctx->enumeration->since = version;
++ entry->since = version;
++
++ if (summary)
++ entry->summary = xstrdup(summary);
++ else
++ entry->summary = NULL;
++ wl_list_insert(ctx->enumeration->entry_list.prev,
++ &entry->link);
++ ctx->entry = entry;
++ } else if (strcmp(element_name, "description") == 0) {
++ if (summary == NULL)
++ fail(&ctx->loc, "description without summary");
++
++ description = xzalloc(sizeof *description);
++ description->summary = xstrdup(summary);
++
++ if (ctx->message)
++ ctx->message->description = description;
++ else if (ctx->entry)
++ ctx->entry->description = description;
++ else if (ctx->enumeration)
++ ctx->enumeration->description = description;
++ else if (ctx->interface)
++ ctx->interface->description = description;
++ else
++ ctx->protocol->description = description;
++ ctx->description = description;
++ }
++}
++
++static struct enumeration *
++find_enumeration(struct protocol *protocol,
++ struct interface *interface,
++ char *enum_attribute)
++{
++ struct interface *i;
++ struct enumeration *e;
++ char *enum_name;
++ uint32_t idx = 0, j;
++
++ for (j = 0; j + 1 < strlen(enum_attribute); j++) {
++ if (enum_attribute[j] == '.') {
++ idx = j;
++ }
++ }
++
++ if (idx > 0) {
++ enum_name = enum_attribute + idx + 1;
++
++ wl_list_for_each(i, &protocol->interface_list, link)
++ if (strncmp(i->name, enum_attribute, idx) == 0)
++ wl_list_for_each(e, &i->enumeration_list, link)
++ if (strcmp(e->name, enum_name) == 0)
++ return e;
++ } else if (interface) {
++ enum_name = enum_attribute;
++
++ wl_list_for_each(e, &interface->enumeration_list, link)
++ if (strcmp(e->name, enum_name) == 0)
++ return e;
++ }
++
++ return NULL;
++}
++
++static void
++verify_arguments(struct parse_context *ctx,
++ struct interface *interface,
++ struct wl_list *messages,
++ struct wl_list *enumerations)
++{
++ struct message *m;
++ wl_list_for_each(m, messages, link) {
++ struct arg *a;
++ wl_list_for_each(a, &m->arg_list, link) {
++ struct enumeration *e;
++
++ if (!a->enumeration_name)
++ continue;
++
++
++ e = find_enumeration(ctx->protocol, interface,
++ a->enumeration_name);
++
++ switch (a->type) {
++ case INT:
++ if (e && e->bitfield)
++ fail(&ctx->loc,
++ "bitfield-style enum must only be referenced by uint");
++ break;
++ case UNSIGNED:
++ break;
++ default:
++ fail(&ctx->loc,
++ "enumeration-style argument has wrong type");
++ }
++ }
++ }
++
++}
++
++#ifndef HAVE_STRNDUP
++char *
++strndup(const char *s, size_t size)
++{
++ char *r = malloc(size + 1);
++ strncpy(r, s, size);
++ r[size] = '\0';
++ return r;
++}
++#endif
++
++static void
++end_element(void *data, const XML_Char *name)
++{
++ struct parse_context *ctx = data;
++
++ if (strcmp(name, "copyright") == 0) {
++ ctx->protocol->copyright =
++ strndup(ctx->character_data,
++ ctx->character_data_length);
++ } else if (strcmp(name, "description") == 0) {
++ ctx->description->text =
++ strndup(ctx->character_data,
++ ctx->character_data_length);
++ ctx->description = NULL;
++ } else if (strcmp(name, "request") == 0 ||
++ strcmp(name, "event") == 0) {
++ ctx->message = NULL;
++ } else if (strcmp(name, "enum") == 0) {
++ if (wl_list_empty(&ctx->enumeration->entry_list)) {
++ fail(&ctx->loc, "enumeration %s was empty",
++ ctx->enumeration->name);
++ }
++ ctx->enumeration = NULL;
++ } else if (strcmp(name, "entry") == 0) {
++ ctx->entry = NULL;
++ } else if (strcmp(name, "protocol") == 0) {
++ struct interface *i;
++
++ wl_list_for_each(i, &ctx->protocol->interface_list, link) {
++ verify_arguments(ctx, i, &i->request_list, &i->enumeration_list);
++ verify_arguments(ctx, i, &i->event_list, &i->enumeration_list);
++ }
++ }
++}
++
++static void
++character_data(void *data, const XML_Char *s, int len)
++{
++ struct parse_context *ctx = data;
++
++ if (ctx->character_data_length + len > sizeof (ctx->character_data)) {
++ fprintf(stderr, "too much character data");
++ exit(EXIT_FAILURE);
++ }
++
++ memcpy(ctx->character_data + ctx->character_data_length, s, len);
++ ctx->character_data_length += len;
++}
++
++static void
++format_text_to_comment(const char *text, bool standalone_comment)
++{
++ int bol = 1, start = 0, i, length;
++ bool comment_started = !standalone_comment;
++
++ length = strlen(text);
++ for (i = 0; i <= length; i++) {
++ if (bol && (text[i] == ' ' || text[i] == '\t')) {
++ continue;
++ } else if (bol) {
++ bol = 0;
++ start = i;
++ }
++ if (text[i] == '\n' ||
++ (text[i] == '\0' && !(start == i))) {
++ printf("%s%s%.*s\n",
++ comment_started ? " *" : "/*",
++ i > start ? " " : "",
++ i - start, text + start);
++ bol = 1;
++ comment_started = true;
++ }
++ }
++ if (comment_started && standalone_comment)
++ printf(" */\n\n");
++}
++
++static void
++emit_opcodes(struct wl_list *message_list, struct interface *interface)
++{
++ struct message *m;
++ int opcode;
++
++ if (wl_list_empty(message_list))
++ return;
++
++ opcode = 0;
++ wl_list_for_each(m, message_list, link)
++ printf("#define %s_%s %d\n",
++ interface->uppercase_name, m->uppercase_name, opcode++);
++
++ printf("\n");
++}
++
++static void
++emit_opcode_versions(struct wl_list *message_list, struct interface *interface)
++{
++ struct message *m;
++
++ wl_list_for_each(m, message_list, link) {
++ printf("/**\n * @ingroup iface_%s\n */\n", interface->name);
++ printf("#define %s_%s_SINCE_VERSION %d\n",
++ interface->uppercase_name, m->uppercase_name, m->since);
++ }
++
++ printf("\n");
++}
++
++static void
++emit_type(struct arg *a)
++{
++ switch (a->type) {
++ default:
++ case INT:
++ case FD:
++ printf("int32_t ");
++ break;
++ case NEW_ID:
++ case UNSIGNED:
++ printf("uint32_t ");
++ break;
++ case FIXED:
++ printf("wl_fixed_t ");
++ break;
++ case STRING:
++ printf("const char *");
++ break;
++ case OBJECT:
++ printf("struct %s *", a->interface_name);
++ break;
++ case ARRAY:
++ printf("struct wl_array *");
++ break;
++ }
++}
++
++static void
++emit_stubs(struct wl_list *message_list, struct interface *interface)
++{
++ struct message *m;
++ struct arg *a, *ret;
++ int has_destructor, has_destroy;
++
++ printf("/** @ingroup iface_%s */\n", interface->name);
++ printf("static inline void\n"
++ "%s_set_user_data(struct %s *%s, void *user_data)\n"
++ "{\n"
++ "\twl_proxy_set_user_data((struct wl_proxy *) %s, user_data);\n"
++ "}\n\n",
++ interface->name, interface->name, interface->name,
++ interface->name);
++
++ printf("/** @ingroup iface_%s */\n", interface->name);
++ printf("static inline void *\n"
++ "%s_get_user_data(struct %s *%s)\n"
++ "{\n"
++ "\treturn wl_proxy_get_user_data((struct wl_proxy *) %s);\n"
++ "}\n\n",
++ interface->name, interface->name, interface->name,
++ interface->name);
++
++ printf("static inline uint32_t\n"
++ "%s_get_version(struct %s *%s)\n"
++ "{\n"
++ "\treturn wl_proxy_get_version((struct wl_proxy *) %s);\n"
++ "}\n\n",
++ interface->name, interface->name, interface->name,
++ interface->name);
++
++ has_destructor = 0;
++ has_destroy = 0;
++ wl_list_for_each(m, message_list, link) {
++ if (m->destructor)
++ has_destructor = 1;
++ if (strcmp(m->name, "destroy") == 0)
++ has_destroy = 1;
++ }
++
++ if (!has_destructor && has_destroy) {
++ fail(&interface->loc,
++ "interface '%s' has method named destroy "
++ "but no destructor",
++ interface->name);
++ exit(EXIT_FAILURE);
++ }
++
++ if (!has_destroy && strcmp(interface->name, "wl_display") != 0) {
++ printf("/** @ingroup iface_%s */\n", interface->name);
++ printf("static inline void\n"
++ "%s_destroy(struct %s *%s)\n"
++ "{\n"
++ "\twl_proxy_destroy("
++ "(struct wl_proxy *) %s);\n"
++ "}\n\n",
++ interface->name, interface->name, interface->name,
++ interface->name);
++ }
++
++ if (wl_list_empty(message_list))
++ return;
++
++ wl_list_for_each(m, message_list, link) {
++ if (m->new_id_count > 1) {
++ warn(&m->loc,
++ "request '%s::%s' has more than "
++ "one new_id arg, not emitting stub\n",
++ interface->name, m->name);
++ continue;
++ }
++
++ ret = NULL;
++ wl_list_for_each(a, &m->arg_list, link) {
++ if (a->type == NEW_ID)
++ ret = a;
++ }
++
++ printf("/**\n"
++ " * @ingroup iface_%s\n", interface->name);
++ if (m->description && m->description->text)
++ format_text_to_comment(m->description->text, false);
++ printf(" */\n");
++ if (ret && ret->interface_name == NULL)
++ printf("static inline void *\n");
++ else if (ret)
++ printf("static inline struct %s *\n",
++ ret->interface_name);
++ else
++ printf("static inline void\n");
++
++ printf("%s_%s(struct %s *%s",
++ interface->name, m->name,
++ interface->name, interface->name);
++
++ wl_list_for_each(a, &m->arg_list, link) {
++ if (a->type == NEW_ID && a->interface_name == NULL) {
++ printf(", const struct wl_interface *interface"
++ ", uint32_t version");
++ continue;
++ } else if (a->type == NEW_ID)
++ continue;
++ printf(", ");
++ emit_type(a);
++ printf("%s", a->name);
++ }
++
++ printf(")\n"
++ "{\n");
++ printf("\t");
++ if (ret) {
++ printf("struct wl_proxy *%s;\n\n"
++ "\t%s = ", ret->name, ret->name);
++ }
++ printf("wl_proxy_marshal_flags("
++ "(struct wl_proxy *) %s,\n"
++ "\t\t\t %s_%s",
++ interface->name,
++ interface->uppercase_name,
++ m->uppercase_name);
++
++ if (ret) {
++ if (ret->interface_name) {
++ /* Normal factory case, an arg has type="new_id" and
++ * an interface is provided */
++ printf(", &%s_interface", ret->interface_name);
++ } else {
++ /* an arg has type ="new_id" but interface is not
++ * provided, such as in wl_registry.bind */
++ printf(", interface");
++ }
++ } else {
++ /* No args have type="new_id" */
++ printf(", NULL");
++ }
++
++ if (ret && ret->interface_name == NULL)
++ printf(", version");
++ else
++ printf(", wl_proxy_get_version((struct wl_proxy *) %s)",
++ interface->name);
++ printf(", %s", m->destructor ? "WL_MARSHAL_FLAG_DESTROY" : "0");
++
++ wl_list_for_each(a, &m->arg_list, link) {
++ if (a->type == NEW_ID) {
++ if (a->interface_name == NULL)
++ printf(", interface->name, version");
++ printf(", NULL");
++ } else {
++ printf(", %s", a->name);
++ }
++ }
++ printf(");\n");
++
++ if (ret && ret->interface_name == NULL)
++ printf("\n\treturn (void *) %s;\n", ret->name);
++ else if (ret)
++ printf("\n\treturn (struct %s *) %s;\n",
++ ret->interface_name, ret->name);
++
++ printf("}\n\n");
++ }
++}
++
++static void
++emit_event_wrappers(struct wl_list *message_list, struct interface *interface)
++{
++ struct message *m;
++ struct arg *a;
++
++ /* We provide hand written functions for the display object */
++ if (strcmp(interface->name, "wl_display") == 0)
++ return;
++
++ wl_list_for_each(m, message_list, link) {
++ printf("/**\n"
++ " * @ingroup iface_%s\n"
++ " * Sends an %s event to the client owning the resource.\n",
++ interface->name,
++ m->name);
++ printf(" * @param resource_ The client's resource\n");
++ wl_list_for_each(a, &m->arg_list, link) {
++ if (a->summary)
++ printf(" * @param %s %s\n", a->name, a->summary);
++ }
++ printf(" */\n");
++ printf("static inline void\n"
++ "%s_send_%s(struct wl_resource *resource_",
++ interface->name, m->name);
++
++ wl_list_for_each(a, &m->arg_list, link) {
++ printf(", ");
++ switch (a->type) {
++ case NEW_ID:
++ case OBJECT:
++ printf("struct wl_resource *");
++ break;
++ default:
++ emit_type(a);
++ }
++ printf("%s", a->name);
++ }
++
++ printf(")\n"
++ "{\n"
++ "\twl_resource_post_event(resource_, %s_%s",
++ interface->uppercase_name, m->uppercase_name);
++
++ wl_list_for_each(a, &m->arg_list, link)
++ printf(", %s", a->name);
++
++ printf(");\n");
++ printf("}\n\n");
++ }
++}
++
++static void
++emit_enumerations(struct interface *interface)
++{
++ struct enumeration *e;
++ struct entry *entry;
++
++ wl_list_for_each(e, &interface->enumeration_list, link) {
++ struct description *desc = e->description;
++
++ printf("#ifndef %s_%s_ENUM\n",
++ interface->uppercase_name, e->uppercase_name);
++ printf("#define %s_%s_ENUM\n",
++ interface->uppercase_name, e->uppercase_name);
++
++ if (desc) {
++ printf("/**\n");
++ printf(" * @ingroup iface_%s\n", interface->name);
++ format_text_to_comment(desc->summary, false);
++ if (desc->text)
++ format_text_to_comment(desc->text, false);
++ printf(" */\n");
++ }
++ printf("enum %s_%s {\n", interface->name, e->name);
++ wl_list_for_each(entry, &e->entry_list, link) {
++ desc = entry->description;
++ if (entry->summary || entry->since > 1 || desc) {
++ printf("\t/**\n");
++ if (entry->summary)
++ printf("\t * %s\n", entry->summary);
++ if (desc) {
++ printf("\t * %s\n", desc->summary);
++ printf("\t *\n");
++ if (desc->text)
++ desc_dump(desc->text, "\t * ");
++ }
++ if (entry->since > 1)
++ printf("\t * @since %d\n", entry->since);
++ printf("\t */\n");
++ }
++ printf("\t%s_%s_%s = %s,\n",
++ interface->uppercase_name,
++ e->uppercase_name,
++ entry->uppercase_name, entry->value);
++ }
++ printf("};\n");
++
++ wl_list_for_each(entry, &e->entry_list, link) {
++ if (entry->since == 1)
++ continue;
++
++ printf("/**\n * @ingroup iface_%s\n */\n", interface->name);
++ printf("#define %s_%s_%s_SINCE_VERSION %d\n",
++ interface->uppercase_name,
++ e->uppercase_name, entry->uppercase_name,
++ entry->since);
++
++ }
++
++ printf("#endif /* %s_%s_ENUM */\n\n",
++ interface->uppercase_name, e->uppercase_name);
++ }
++}
++
++static void
++emit_structs(struct wl_list *message_list, struct interface *interface, enum side side)
++{
++ struct message *m;
++ struct arg *a;
++ int n;
++
++ if (wl_list_empty(message_list))
++ return;
++
++ printf("/**\n");
++ printf(" * @ingroup iface_%s\n", interface->name);
++ printf(" * @struct %s_%s\n", interface->name,
++ (side == SERVER) ? "interface" : "listener");
++ printf(" */\n");
++ printf("struct %s_%s {\n", interface->name,
++ (side == SERVER) ? "interface" : "listener");
++
++ wl_list_for_each(m, message_list, link) {
++ struct description *mdesc = m->description;
++
++ printf("\t/**\n");
++ if (mdesc) {
++ if (mdesc->summary)
++ printf("\t * %s\n", mdesc->summary);
++ printf("\t *\n");
++ desc_dump(mdesc->text, "\t * ");
++ }
++ wl_list_for_each(a, &m->arg_list, link) {
++ if (side == SERVER && a->type == NEW_ID &&
++ a->interface_name == NULL)
++ printf("\t * @param interface name of the objects interface\n"
++ "\t * @param version version of the objects interface\n");
++
++ if (a->summary)
++ printf("\t * @param %s %s\n", a->name,
++ a->summary);
++ }
++ if (m->since > 1) {
++ printf("\t * @since %d\n", m->since);
++ }
++ printf("\t */\n");
++ printf("\tvoid (*%s)(", m->name);
++
++ n = strlen(m->name) + 17;
++ if (side == SERVER) {
++ printf("struct wl_client *client,\n"
++ "%sstruct wl_resource *resource",
++ indent(n));
++ } else {
++ printf("void *data,\n"),
++ printf("%sstruct %s *%s",
++ indent(n), interface->name, interface->name);
++ }
++
++ wl_list_for_each(a, &m->arg_list, link) {
++ printf(",\n%s", indent(n));
++
++ if (side == SERVER && a->type == OBJECT)
++ printf("struct wl_resource *");
++ else if (side == SERVER && a->type == NEW_ID && a->interface_name == NULL)
++ printf("const char *interface, uint32_t version, uint32_t ");
++ else if (side == CLIENT && a->type == OBJECT && a->interface_name == NULL)
++ printf("void *");
++
++ else if (side == CLIENT && a->type == NEW_ID)
++ printf("struct %s *", a->interface_name);
++ else
++ emit_type(a);
++
++ printf("%s", a->name);
++ }
++
++ printf(");\n");
++ }
++
++ printf("};\n\n");
++
++ if (side == CLIENT) {
++ printf("/**\n"
++ " * @ingroup iface_%s\n"
++ " */\n", interface->name);
++ printf("static inline int\n"
++ "%s_add_listener(struct %s *%s,\n"
++ "%sconst struct %s_listener *listener, void *data)\n"
++ "{\n"
++ "\treturn wl_proxy_add_listener((struct wl_proxy *) %s,\n"
++ "%s(void (**)(void)) listener, data);\n"
++ "}\n\n",
++ interface->name, interface->name, interface->name,
++ indent(14 + strlen(interface->name)),
++ interface->name,
++ interface->name,
++ indent(37));
++ }
++}
++
++static void
++emit_types_forward_declarations(struct protocol *protocol,
++ struct wl_list *message_list,
++ struct wl_array *types)
++{
++ struct message *m;
++ struct arg *a;
++ int length;
++ char **p;
++
++ wl_list_for_each(m, message_list, link) {
++ length = 0;
++ m->all_null = 1;
++ wl_list_for_each(a, &m->arg_list, link) {
++ length++;
++ switch (a->type) {
++ case NEW_ID:
++ case OBJECT:
++ if (!a->interface_name)
++ continue;
++
++ m->all_null = 0;
++ p = fail_on_null(wl_array_add(types, sizeof *p));
++ *p = a->interface_name;
++ break;
++ default:
++ break;
++ }
++ }
++
++ if (m->all_null && length > protocol->null_run_length)
++ protocol->null_run_length = length;
++ }
++}
++
++static int
++cmp_names(const void *p1, const void *p2)
++{
++ const char * const *s1 = p1, * const *s2 = p2;
++
++ return strcmp(*s1, *s2);
++}
++
++static const char *
++get_include_name(bool core, enum side side)
++{
++ if (side == SERVER)
++ return core ? "wayland-server-core.h" : "wayland-server.h";
++ else
++ return core ? "wayland-client-core.h" : "wayland-client.h";
++}
++
++static void
++emit_mainpage_blurb(const struct protocol *protocol, enum side side)
++{
++ struct interface *i;
++
++ printf("/**\n"
++ " * @page page_%s The %s protocol\n",
++ protocol->name, protocol->name);
++
++ if (protocol->description) {
++ if (protocol->description->summary) {
++ printf(" * %s\n"
++ " *\n", protocol->description->summary);
++ }
++
++ if (protocol->description->text) {
++ printf(" * @section page_desc_%s Description\n", protocol->name);
++ format_text_to_comment(protocol->description->text, false);
++ printf(" *\n");
++ }
++ }
++
++ printf(" * @section page_ifaces_%s Interfaces\n", protocol->name);
++ wl_list_for_each(i, &protocol->interface_list, link) {
++ printf(" * - @subpage page_iface_%s - %s\n",
++ i->name,
++ i->description && i->description->summary ? i->description->summary : "");
++ }
++
++ if (protocol->copyright) {
++ printf(" * @section page_copyright_%s Copyright\n",
++ protocol->name);
++ printf(" * <pre>\n");
++ format_text_to_comment(protocol->copyright, false);
++ printf(" * </pre>\n");
++ }
++
++ printf(" */\n");
++}
++
++static void
++emit_header(struct protocol *protocol, enum side side)
++{
++ struct interface *i, *i_next;
++ struct wl_array types;
++ const char *s = (side == SERVER) ? "SERVER" : "CLIENT";
++ char **p, *prev;
++
++ printf("/* Generated by %s %s */\n\n", PROGRAM_NAME, WAYLAND_VERSION);
++
++ printf("#ifndef %s_%s_PROTOCOL_H\n"
++ "#define %s_%s_PROTOCOL_H\n"
++ "\n"
++ "#include <stdint.h>\n"
++ "#include <stddef.h>\n"
++ "#include \"%s\"\n\n"
++ "#ifdef __cplusplus\n"
++ "extern \"C\" {\n"
++ "#endif\n\n",
++ protocol->uppercase_name, s,
++ protocol->uppercase_name, s,
++ get_include_name(protocol->core_headers, side));
++ if (side == SERVER)
++ printf("struct wl_client;\n"
++ "struct wl_resource;\n\n");
++
++ emit_mainpage_blurb(protocol, side);
++
++ wl_array_init(&types);
++ wl_list_for_each(i, &protocol->interface_list, link) {
++ emit_types_forward_declarations(protocol, &i->request_list, &types);
++ emit_types_forward_declarations(protocol, &i->event_list, &types);
++ }
++
++ wl_list_for_each(i, &protocol->interface_list, link) {
++ p = fail_on_null(wl_array_add(&types, sizeof *p));
++ *p = i->name;
++ }
++
++ qsort(types.data, types.size / sizeof *p, sizeof *p, cmp_names);
++ prev = NULL;
++ wl_array_for_each(p, &types) {
++ if (prev && strcmp(*p, prev) == 0)
++ continue;
++ printf("struct %s;\n", *p);
++ prev = *p;
++ }
++ wl_array_release(&types);
++ printf("\n");
++
++ wl_list_for_each(i, &protocol->interface_list, link) {
++ printf("#ifndef %s_INTERFACE\n", i->uppercase_name);
++ printf("#define %s_INTERFACE\n", i->uppercase_name);
++ printf("/**\n"
++ " * @page page_iface_%s %s\n",
++ i->name, i->name);
++ if (i->description && i->description->text) {
++ printf(" * @section page_iface_%s_desc Description\n",
++ i->name);
++ format_text_to_comment(i->description->text, false);
++ }
++ printf(" * @section page_iface_%s_api API\n"
++ " * See @ref iface_%s.\n"
++ " */\n",
++ i->name, i->name);
++ printf("/**\n"
++ " * @defgroup iface_%s The %s interface\n",
++ i->name, i->name);
++ if (i->description && i->description->text)
++ format_text_to_comment(i->description->text, false);
++ printf(" */\n");
++ printf("extern const struct wl_interface "
++ "%s_interface;\n", i->name);
++ printf("#endif\n");
++ }
++
++ printf("\n");
++
++ wl_list_for_each_safe(i, i_next, &protocol->interface_list, link) {
++
++ emit_enumerations(i);
++
++ if (side == SERVER) {
++ emit_structs(&i->request_list, i, side);
++ emit_opcodes(&i->event_list, i);
++ emit_opcode_versions(&i->event_list, i);
++ emit_opcode_versions(&i->request_list, i);
++ emit_event_wrappers(&i->event_list, i);
++ } else {
++ emit_structs(&i->event_list, i, side);
++ emit_opcodes(&i->request_list, i);
++ emit_opcode_versions(&i->event_list, i);
++ emit_opcode_versions(&i->request_list, i);
++ emit_stubs(&i->request_list, i);
++ }
++
++ free_interface(i);
++ }
++
++ printf("#ifdef __cplusplus\n"
++ "}\n"
++ "#endif\n"
++ "\n"
++ "#endif\n");
++}
++
++static void
++emit_null_run(struct protocol *protocol)
++{
++ int i;
++
++ for (i = 0; i < protocol->null_run_length; i++)
++ printf("\tNULL,\n");
++}
++
++static void
++emit_types(struct protocol *protocol, struct wl_list *message_list)
++{
++ struct message *m;
++ struct arg *a;
++
++ wl_list_for_each(m, message_list, link) {
++ if (m->all_null) {
++ m->type_index = 0;
++ continue;
++ }
++
++ m->type_index =
++ protocol->null_run_length + protocol->type_index;
++ protocol->type_index += m->arg_count;
++
++ wl_list_for_each(a, &m->arg_list, link) {
++ switch (a->type) {
++ case NEW_ID:
++ case OBJECT:
++ if (a->interface_name)
++ printf("\t&%s_interface,\n",
++ a->interface_name);
++ else
++ printf("\tNULL,\n");
++ break;
++ default:
++ printf("\tNULL,\n");
++ break;
++ }
++ }
++ }
++}
++
++static void
++emit_messages(const char *name, struct wl_list *message_list,
++ struct interface *interface, const char *suffix)
++{
++ struct message *m;
++ struct arg *a;
++
++ if (wl_list_empty(message_list))
++ return;
++
++ printf("static const struct wl_message "
++ "%s_%s[] = {\n",
++ interface->name, suffix);
++
++ wl_list_for_each(m, message_list, link) {
++ printf("\t{ \"%s\", \"", m->name);
++
++ if (m->since > 1)
++ printf("%d", m->since);
++
++ wl_list_for_each(a, &m->arg_list, link) {
++ if (is_nullable_type(a) && a->nullable)
++ printf("?");
++
++ switch (a->type) {
++ default:
++ case INT:
++ printf("i");
++ break;
++ case NEW_ID:
++ if (a->interface_name == NULL)
++ printf("su");
++ printf("n");
++ break;
++ case UNSIGNED:
++ printf("u");
++ break;
++ case FIXED:
++ printf("f");
++ break;
++ case STRING:
++ printf("s");
++ break;
++ case OBJECT:
++ printf("o");
++ break;
++ case ARRAY:
++ printf("a");
++ break;
++ case FD:
++ printf("h");
++ break;
++ }
++ }
++ printf("\", %s_types + %d },\n", name, m->type_index);
++ }
++
++ printf("};\n\n");
++}
++
++
++static void
++emit_code(struct protocol *protocol, enum visibility vis)
++{
++ const char *symbol_visibility;
++ struct interface *i, *next;
++ struct wl_array types;
++ char **p, *prev;
++
++ printf("/* Generated by %s %s */\n\n", PROGRAM_NAME, WAYLAND_VERSION);
++
++ if (protocol->copyright)
++ format_text_to_comment(protocol->copyright, true);
++
++ printf("#include <stdlib.h>\n"
++ "#include <stdint.h>\n"
++ "#include \"wayland-util.h\"\n\n");
++
++ /* When building a shared library symbols must be exported, otherwise
++ * we want to have the symbols hidden. */
++ if (vis == PRIVATE) {
++ symbol_visibility = "WL_PRIVATE";
++ printf("#ifndef __has_attribute\n"
++ "# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */\n"
++ "#endif\n\n");
++
++ printf("#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)\n"
++ "#define WL_PRIVATE __attribute__ ((visibility(\"hidden\")))\n"
++ "#else\n"
++ "#define WL_PRIVATE\n"
++ "#endif\n\n");
++ } else {
++ symbol_visibility = "WL_EXPORT";
++ }
++
++ wl_array_init(&types);
++ wl_list_for_each(i, &protocol->interface_list, link) {
++ emit_types_forward_declarations(protocol, &i->request_list, &types);
++ emit_types_forward_declarations(protocol, &i->event_list, &types);
++ }
++ qsort(types.data, types.size / sizeof *p, sizeof *p, cmp_names);
++ prev = NULL;
++ wl_array_for_each(p, &types) {
++ if (prev && strcmp(*p, prev) == 0)
++ continue;
++ printf("extern const struct wl_interface %s_interface;\n", *p);
++ prev = *p;
++ }
++ wl_array_release(&types);
++ printf("\n");
++
++ printf("static const struct wl_interface *%s_types[] = {\n", protocol->name);
++ emit_null_run(protocol);
++ wl_list_for_each(i, &protocol->interface_list, link) {
++ emit_types(protocol, &i->request_list);
++ emit_types(protocol, &i->event_list);
++ }
++ printf("};\n\n");
++
++ wl_list_for_each_safe(i, next, &protocol->interface_list, link) {
++
++ emit_messages(protocol->name, &i->request_list, i, "requests");
++ emit_messages(protocol->name, &i->event_list, i, "events");
++
++ printf("%s const struct wl_interface "
++ "%s_interface = {\n"
++ "\t\"%s\", %d,\n",
++ symbol_visibility, i->name, i->name, i->version);
++
++ if (!wl_list_empty(&i->request_list))
++ printf("\t%d, %s_requests,\n",
++ wl_list_length(&i->request_list), i->name);
++ else
++ printf("\t0, NULL,\n");
++
++ if (!wl_list_empty(&i->event_list))
++ printf("\t%d, %s_events,\n",
++ wl_list_length(&i->event_list), i->name);
++ else
++ printf("\t0, NULL,\n");
++
++ printf("};\n\n");
++
++ /* we won't need it any further */
++ free_interface(i);
++ }
++}
++
++static void
++free_protocol(struct protocol *protocol)
++{
++ free(protocol->name);
++ free(protocol->uppercase_name);
++ free(protocol->copyright);
++ free_description(protocol->description);
++}
++
++int main(int argc, char *argv[])
++{
++ struct parse_context ctx;
++ struct protocol protocol;
++ FILE *input = stdin;
++ char *input_filename = NULL;
++ int len;
++ void *buf;
++ bool help = false;
++ bool core_headers = false;
++ bool version = false;
++ bool strict = false;
++ bool fail = false;
++ int opt;
++ enum {
++ CLIENT_HEADER,
++ SERVER_HEADER,
++ PRIVATE_CODE,
++ PUBLIC_CODE,
++ CODE,
++ } mode;
++
++ static const struct option options[] = {
++ { "help", no_argument, NULL, 'h' },
++ { "version", no_argument, NULL, 'v' },
++ { "include-core-only", no_argument, NULL, 'c' },
++ { "strict", no_argument, NULL, 's' },
++ { 0, 0, NULL, 0 }
++ };
++
++ while (1) {
++ opt = getopt_long(argc, argv, "hvcs", options, NULL);
++
++ if (opt == -1)
++ break;
++
++ switch (opt) {
++ case 'h':
++ help = true;
++ break;
++ case 'v':
++ version = true;
++ break;
++ case 'c':
++ core_headers = true;
++ break;
++ case 's':
++ strict = true;
++ break;
++ default:
++ fail = true;
++ break;
++ }
++ }
++
++ argv += optind;
++ argc -= optind;
++
++ if (help)
++ usage(EXIT_SUCCESS);
++ else if (version)
++ scanner_version(EXIT_SUCCESS);
++ else if ((argc != 1 && argc != 3) || fail)
++ usage(EXIT_FAILURE);
++ else if (strcmp(argv[0], "help") == 0)
++ usage(EXIT_SUCCESS);
++ else if (strcmp(argv[0], "client-header") == 0)
++ mode = CLIENT_HEADER;
++ else if (strcmp(argv[0], "server-header") == 0)
++ mode = SERVER_HEADER;
++ else if (strcmp(argv[0], "private-code") == 0)
++ mode = PRIVATE_CODE;
++ else if (strcmp(argv[0], "public-code") == 0)
++ mode = PUBLIC_CODE;
++ else if (strcmp(argv[0], "code") == 0)
++ mode = CODE;
++ else
++ usage(EXIT_FAILURE);
++
++ if (argc == 3) {
++ input_filename = argv[1];
++ input = fopen(input_filename, "r");
++ if (input == NULL) {
++ fprintf(stderr, "Could not open input file: %s\n",
++ strerror(errno));
++ exit(EXIT_FAILURE);
++ }
++ if (freopen(argv[2], "w", stdout) == NULL) {
++ fprintf(stderr, "Could not open output file: %s\n",
++ strerror(errno));
++ fclose(input);
++ exit(EXIT_FAILURE);
++ }
++ }
++
++ /* initialize protocol structure */
++ memset(&protocol, 0, sizeof protocol);
++ wl_list_init(&protocol.interface_list);
++ protocol.core_headers = core_headers;
++
++ /* initialize context */
++ memset(&ctx, 0, sizeof ctx);
++ ctx.protocol = &protocol;
++ if (input == stdin)
++ ctx.loc.filename = "<stdin>";
++ else
++ ctx.loc.filename = input_filename;
++
++ if (!is_dtd_valid(input, ctx.loc.filename)) {
++ fprintf(stderr,
++ "*******************************************************\n"
++ "* *\n"
++ "* WARNING: XML failed validation against built-in DTD *\n"
++ "* *\n"
++ "*******************************************************\n");
++ if (strict) {
++ fclose(input);
++ exit(EXIT_FAILURE);
++ }
++ }
++
++ /* create XML parser */
++ ctx.parser = XML_ParserCreate(NULL);
++ XML_SetUserData(ctx.parser, &ctx);
++ if (ctx.parser == NULL) {
++ fprintf(stderr, "failed to create parser\n");
++ fclose(input);
++ exit(EXIT_FAILURE);
++ }
++
++ XML_SetElementHandler(ctx.parser, start_element, end_element);
++ XML_SetCharacterDataHandler(ctx.parser, character_data);
++
++ do {
++ buf = XML_GetBuffer(ctx.parser, XML_BUFFER_SIZE);
++ len = fread(buf, 1, XML_BUFFER_SIZE, input);
++ if (len < 0) {
++ fprintf(stderr, "fread: %s\n", strerror(errno));
++ fclose(input);
++ exit(EXIT_FAILURE);
++ }
++ if (XML_ParseBuffer(ctx.parser, len, len == 0) == 0) {
++ fprintf(stderr,
++ "Error parsing XML at line %ld col %ld: %s\n",
++ XML_GetCurrentLineNumber(ctx.parser),
++ XML_GetCurrentColumnNumber(ctx.parser),
++ XML_ErrorString(XML_GetErrorCode(ctx.parser)));
++ fclose(input);
++ exit(EXIT_FAILURE);
++ }
++ } while (len > 0);
++
++ XML_ParserFree(ctx.parser);
++
++ switch (mode) {
++ case CLIENT_HEADER:
++ emit_header(&protocol, CLIENT);
++ break;
++ case SERVER_HEADER:
++ emit_header(&protocol, SERVER);
++ break;
++ case PRIVATE_CODE:
++ emit_code(&protocol, PRIVATE);
++ break;
++ case CODE:
++ fprintf(stderr,
++ "Using \"code\" is deprecated - use "
++ "private-code or public-code.\n"
++ "See the help page for details.\n");
++ /* fallthrough */
++ case PUBLIC_CODE:
++ emit_code(&protocol, PUBLIC);
++ break;
++ }
++
++ free_protocol(&protocol);
++ fclose(input);
++
++ return 0;
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_CLIENT_CORE_H
++#define WAYLAND_CLIENT_CORE_H
++
++#include <stdint.h>
++#include "wayland-util.h"
++#include "wayland-version.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/** \class wl_proxy
++ *
++ * \brief Represents a protocol object on the client side.
++ *
++ * A wl_proxy acts as a client side proxy to an object existing in the
++ * compositor. The proxy is responsible for converting requests made by the
++ * clients with \ref wl_proxy_marshal() into Wayland's wire format. Events
++ * coming from the compositor are also handled by the proxy, which will in
++ * turn call the handler set with \ref wl_proxy_add_listener().
++ *
++ * \note With the exception of function \ref wl_proxy_set_queue(), functions
++ * accessing a wl_proxy are not normally used by client code. Clients
++ * should normally use the higher level interface generated by the scanner to
++ * interact with compositor objects.
++ *
++ */
++struct wl_proxy;
++
++/** \class wl_display
++ *
++ * \brief Represents a connection to the compositor and acts as a proxy to
++ * the wl_display singleton object.
++ *
++ * A wl_display object represents a client connection to a Wayland
++ * compositor. It is created with either \ref wl_display_connect() or
++ * \ref wl_display_connect_to_fd(). A connection is terminated using
++ * \ref wl_display_disconnect().
++ *
++ * A wl_display is also used as the \ref wl_proxy for the wl_display
++ * singleton object on the compositor side.
++ *
++ * A wl_display object handles all the data sent from and to the
++ * compositor. When a \ref wl_proxy marshals a request, it will write its wire
++ * representation to the display's write buffer. The data is sent to the
++ * compositor when the client calls \ref wl_display_flush().
++ *
++ * Incoming data is handled in two steps: queueing and dispatching. In the
++ * queue step, the data coming from the display fd is interpreted and
++ * added to a queue. On the dispatch step, the handler for the incoming
++ * event set by the client on the corresponding \ref wl_proxy is called.
++ *
++ * A wl_display has at least one event queue, called the <em>default
++ * queue</em>. Clients can create additional event queues with \ref
++ * wl_display_create_queue() and assign \ref wl_proxy's to it. Events
++ * occurring in a particular proxy are always queued in its assigned queue.
++ * A client can ensure that a certain assumption, such as holding a lock
++ * or running from a given thread, is true when a proxy event handler is
++ * called by assigning that proxy to an event queue and making sure that
++ * this queue is only dispatched when the assumption holds.
++ *
++ * The default queue is dispatched by calling \ref wl_display_dispatch().
++ * This will dispatch any events queued on the default queue and attempt
++ * to read from the display fd if it's empty. Events read are then queued
++ * on the appropriate queues according to the proxy assignment.
++ *
++ * A user created queue is dispatched with \ref wl_display_dispatch_queue().
++ * This function behaves exactly the same as wl_display_dispatch()
++ * but it dispatches given queue instead of the default queue.
++ *
++ * A real world example of event queue usage is Mesa's implementation of
++ * eglSwapBuffers() for the Wayland platform. This function might need
++ * to block until a frame callback is received, but dispatching the default
++ * queue could cause an event handler on the client to start drawing
++ * again. This problem is solved using another event queue, so that only
++ * the events handled by the EGL code are dispatched during the block.
++ *
++ * This creates a problem where a thread dispatches a non-default
++ * queue, reading all the data from the display fd. If the application
++ * would call \em poll(2) after that it would block, even though there
++ * might be events queued on the default queue. Those events should be
++ * dispatched with \ref wl_display_dispatch_pending() or \ref
++ * wl_display_dispatch_queue_pending() before flushing and blocking.
++ */
++struct wl_display;
++
++/** \class wl_event_queue
++ *
++ * \brief A queue for \ref wl_proxy object events.
++ *
++ * Event queues allows the events on a display to be handled in a thread-safe
++ * manner. See \ref wl_display for details.
++ *
++ */
++struct wl_event_queue;
++
++/** Destroy proxy after marshalling
++ * @ingroup wl_proxy
++ */
++#define WL_MARSHAL_FLAG_DESTROY (1 << 0)
++
++void
++wl_event_queue_destroy(struct wl_event_queue *queue);
++
++struct wl_proxy *
++wl_proxy_marshal_flags(struct wl_proxy *proxy, uint32_t opcode,
++ const struct wl_interface *interface,
++ uint32_t version,
++ uint32_t flags, ...);
++
++struct wl_proxy *
++wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode,
++ const struct wl_interface *interface,
++ uint32_t version,
++ uint32_t flags,
++ union wl_argument *args);
++
++void
++wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...);
++
++void
++wl_proxy_marshal_array(struct wl_proxy *p, uint32_t opcode,
++ union wl_argument *args);
++
++struct wl_proxy *
++wl_proxy_create(struct wl_proxy *factory,
++ const struct wl_interface *interface);
++
++void *
++wl_proxy_create_wrapper(void *proxy);
++
++void
++wl_proxy_wrapper_destroy(void *proxy_wrapper);
++
++struct wl_proxy *
++wl_proxy_marshal_constructor(struct wl_proxy *proxy,
++ uint32_t opcode,
++ const struct wl_interface *interface,
++ ...);
++
++struct wl_proxy *
++wl_proxy_marshal_constructor_versioned(struct wl_proxy *proxy,
++ uint32_t opcode,
++ const struct wl_interface *interface,
++ uint32_t version,
++ ...);
++
++struct wl_proxy *
++wl_proxy_marshal_array_constructor(struct wl_proxy *proxy,
++ uint32_t opcode, union wl_argument *args,
++ const struct wl_interface *interface);
++
++struct wl_proxy *
++wl_proxy_marshal_array_constructor_versioned(struct wl_proxy *proxy,
++ uint32_t opcode,
++ union wl_argument *args,
++ const struct wl_interface *interface,
++ uint32_t version);
++
++void
++wl_proxy_destroy(struct wl_proxy *proxy);
++
++int
++wl_proxy_add_listener(struct wl_proxy *proxy,
++ void (**implementation)(void), void *data);
++
++const void *
++wl_proxy_get_listener(struct wl_proxy *proxy);
++
++int
++wl_proxy_add_dispatcher(struct wl_proxy *proxy,
++ wl_dispatcher_func_t dispatcher_func,
++ const void * dispatcher_data, void *data);
++
++void
++wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data);
++
++void *
++wl_proxy_get_user_data(struct wl_proxy *proxy);
++
++uint32_t
++wl_proxy_get_version(struct wl_proxy *proxy);
++
++uint32_t
++wl_proxy_get_id(struct wl_proxy *proxy);
++
++void
++wl_proxy_set_tag(struct wl_proxy *proxy,
++ const char * const *tag);
++
++const char * const *
++wl_proxy_get_tag(struct wl_proxy *proxy);
++
++const char *
++wl_proxy_get_class(struct wl_proxy *proxy);
++
++void
++wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue);
++
++struct wl_display *
++wl_display_connect(const char *name);
++
++struct wl_display *
++wl_display_connect_to_fd(int fd);
++
++void
++wl_display_disconnect(struct wl_display *display);
++
++int
++wl_display_get_fd(struct wl_display *display);
++
++int
++wl_display_dispatch(struct wl_display *display);
++
++int
++wl_display_dispatch_queue(struct wl_display *display,
++ struct wl_event_queue *queue);
++
++int
++wl_display_dispatch_queue_pending(struct wl_display *display,
++ struct wl_event_queue *queue);
++
++int
++wl_display_dispatch_pending(struct wl_display *display);
++
++int
++wl_display_get_error(struct wl_display *display);
++
++uint32_t
++wl_display_get_protocol_error(struct wl_display *display,
++ const struct wl_interface **interface,
++ uint32_t *id);
++
++int
++wl_display_flush(struct wl_display *display);
++
++int
++wl_display_roundtrip_queue(struct wl_display *display,
++ struct wl_event_queue *queue);
++
++int
++wl_display_roundtrip(struct wl_display *display);
++
++struct wl_event_queue *
++wl_display_create_queue(struct wl_display *display);
++
++int
++wl_display_prepare_read_queue(struct wl_display *display,
++ struct wl_event_queue *queue);
++
++int
++wl_display_prepare_read(struct wl_display *display);
++
++void
++wl_display_cancel_read(struct wl_display *display);
++
++int
++wl_display_read_events(struct wl_display *display);
++
++void
++wl_log_set_handler_client(wl_log_func_t handler);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2008-2012 Kristian Høgsberg
++ * Copyright © 2010-2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++
++#include <stdlib.h>
++#include <stdint.h>
++#include <stddef.h>
++#include <stdio.h>
++#include <stdbool.h>
++#include <errno.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <ctype.h>
++#include <assert.h>
++#include <fcntl.h>
++#include <poll.h>
++#include <pthread.h>
++
++#include "wayland-util.h"
++#include "wayland-os.h"
++#include "wayland-client.h"
++#include "wayland-private.h"
++
++/** \cond */
++
++enum wl_proxy_flag {
++ WL_PROXY_FLAG_ID_DELETED = (1 << 0),
++ WL_PROXY_FLAG_DESTROYED = (1 << 1),
++ WL_PROXY_FLAG_WRAPPER = (1 << 2),
++};
++
++struct wl_zombie {
++ int event_count;
++ int *fd_count;
++};
++
++struct wl_proxy {
++ struct wl_object object;
++ struct wl_display *display;
++ struct wl_event_queue *queue;
++ uint32_t flags;
++ int refcount;
++ void *user_data;
++ wl_dispatcher_func_t dispatcher;
++ uint32_t version;
++ const char * const *tag;
++};
++
++struct wl_event_queue {
++ struct wl_list event_list;
++ struct wl_display *display;
++};
++
++struct wl_display {
++ struct wl_proxy proxy;
++ struct wl_connection *connection;
++
++ /* errno of the last wl_display error */
++ int last_error;
++
++ /* When display gets an error event from some object, it stores
++ * information about it here, so that client can get this
++ * information afterwards */
++ struct {
++ /* Code of the error. It can be compared to
++ * the interface's errors enumeration. */
++ uint32_t code;
++ /* interface (protocol) in which the error occurred */
++ const struct wl_interface *interface;
++ /* id of the proxy that caused the error. There's no warranty
++ * that the proxy is still valid. It's up to client how it will
++ * use it */
++ uint32_t id;
++ } protocol_error;
++ int fd;
++ struct wl_map objects;
++ struct wl_event_queue display_queue;
++ struct wl_event_queue default_queue;
++ pthread_mutex_t mutex;
++
++ int reader_count;
++ uint32_t read_serial;
++ pthread_cond_t reader_cond;
++};
++
++/** \endcond */
++
++static int debug_client = 0;
++
++/**
++ * This helper function wakes up all threads that are
++ * waiting for display->reader_cond (i. e. when reading is done,
++ * canceled, or an error occurred)
++ *
++ * NOTE: must be called with display->mutex locked
++ */
++static void
++display_wakeup_threads(struct wl_display *display)
++{
++ /* Thread can get sleeping only in read_events(). If we're
++ * waking it up, it means that the read completed or was
++ * canceled, so we must increase the read_serial.
++ * This prevents from indefinite sleeping in read_events().
++ */
++ ++display->read_serial;
++
++ pthread_cond_broadcast(&display->reader_cond);
++}
++
++/**
++ * This function is called for local errors (no memory, server hung up)
++ *
++ * \param display
++ * \param error error value (EINVAL, EFAULT, ...)
++ *
++ * \note this function is called with display mutex locked
++ */
++static void
++display_fatal_error(struct wl_display *display, int error)
++{
++ if (display->last_error)
++ return;
++
++ if (!error)
++ error = EFAULT;
++
++ display->last_error = error;
++
++ display_wakeup_threads(display);
++}
++
++/**
++ * This function is called for error events
++ * and indicates that in some object an error occurred.
++ * The difference between this function and display_fatal_error()
++ * is that this one handles errors that will come by wire,
++ * whereas display_fatal_error() is called for local errors.
++ *
++ * \param display
++ * \param code error code
++ * \param id id of the object that generated the error
++ * \param intf protocol interface
++ */
++static void
++display_protocol_error(struct wl_display *display, uint32_t code,
++ uint32_t id, const struct wl_interface *intf)
++{
++ int err;
++
++ if (display->last_error)
++ return;
++
++ /* set correct errno */
++ if (intf && wl_interface_equal(intf, &wl_display_interface)) {
++ switch (code) {
++ case WL_DISPLAY_ERROR_INVALID_OBJECT:
++ case WL_DISPLAY_ERROR_INVALID_METHOD:
++ err = EINVAL;
++ break;
++ case WL_DISPLAY_ERROR_NO_MEMORY:
++ err = ENOMEM;
++ break;
++ case WL_DISPLAY_ERROR_IMPLEMENTATION:
++ err = EPROTO;
++ break;
++ default:
++ err = EFAULT;
++ }
++ } else {
++ err = EPROTO;
++ }
++
++ pthread_mutex_lock(&display->mutex);
++
++ display->last_error = err;
++
++ display->protocol_error.code = code;
++ display->protocol_error.id = id;
++ display->protocol_error.interface = intf;
++
++ /*
++ * here it is not necessary to wake up threads like in
++ * display_fatal_error, because this function is called from
++ * an event handler and that means that read_events() is done
++ * and woke up all threads. Since wl_display_prepare_read()
++ * fails when there are events in the queue, no threads
++ * can sleep in read_events() during dispatching
++ * (and therefore during calling this function), so this is safe.
++ */
++
++ pthread_mutex_unlock(&display->mutex);
++}
++
++static void
++wl_event_queue_init(struct wl_event_queue *queue, struct wl_display *display)
++{
++ wl_list_init(&queue->event_list);
++ queue->display = display;
++}
++
++static void
++wl_proxy_unref(struct wl_proxy *proxy)
++{
++ assert(proxy->refcount > 0);
++ if (--proxy->refcount > 0)
++ return;
++
++ /* If we get here, the client must have explicitly requested
++ * deletion. */
++ assert(proxy->flags & WL_PROXY_FLAG_DESTROYED);
++ free(proxy);
++}
++
++static void
++validate_closure_objects(struct wl_closure *closure)
++{
++ const char *signature;
++ struct argument_details arg;
++ int i, count;
++ struct wl_proxy *proxy;
++
++ signature = closure->message->signature;
++ count = arg_count_for_signature(signature);
++ for (i = 0; i < count; i++) {
++ signature = get_next_argument(signature, &arg);
++ switch (arg.type) {
++ case 'n':
++ case 'o':
++ proxy = (struct wl_proxy *) closure->args[i].o;
++ if (proxy && proxy->flags & WL_PROXY_FLAG_DESTROYED)
++ closure->args[i].o = NULL;
++ break;
++ default:
++ break;
++ }
++ }
++}
++
++/* Destroys a closure which was demarshaled for dispatch; unrefs all the
++ * proxies in its arguments, as well as its own proxy, and destroys the
++ * closure itself. */
++static void
++destroy_queued_closure(struct wl_closure *closure)
++{
++ const char *signature;
++ struct argument_details arg;
++ struct wl_proxy *proxy;
++ int i, count;
++
++ signature = closure->message->signature;
++ count = arg_count_for_signature(signature);
++ for (i = 0; i < count; i++) {
++ signature = get_next_argument(signature, &arg);
++ switch (arg.type) {
++ case 'n':
++ case 'o':
++ proxy = (struct wl_proxy *) closure->args[i].o;
++ if (proxy)
++ wl_proxy_unref(proxy);
++ break;
++ default:
++ break;
++ }
++ }
++
++ wl_proxy_unref(closure->proxy);
++ wl_closure_destroy(closure);
++}
++
++static void
++wl_event_queue_release(struct wl_event_queue *queue)
++{
++ struct wl_closure *closure;
++
++ while (!wl_list_empty(&queue->event_list)) {
++ closure = wl_container_of(queue->event_list.next,
++ closure, link);
++ wl_list_remove(&closure->link);
++ destroy_queued_closure(closure);
++ }
++}
++
++/** Destroy an event queue
++ *
++ * \param queue The event queue to be destroyed
++ *
++ * Destroy the given event queue. Any pending event on that queue is
++ * discarded.
++ *
++ * The \ref wl_display object used to create the queue should not be
++ * destroyed until all event queues created with it are destroyed with
++ * this function.
++ *
++ * \memberof wl_event_queue
++ */
++WL_EXPORT void
++wl_event_queue_destroy(struct wl_event_queue *queue)
++{
++ struct wl_display *display = queue->display;
++
++ pthread_mutex_lock(&display->mutex);
++ wl_event_queue_release(queue);
++ free(queue);
++ pthread_mutex_unlock(&display->mutex);
++}
++
++/** Create a new event queue for this display
++ *
++ * \param display The display context object
++ * \return A new event queue associated with this display or NULL on
++ * failure.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT struct wl_event_queue *
++wl_display_create_queue(struct wl_display *display)
++{
++ struct wl_event_queue *queue;
++
++ queue = zalloc(sizeof *queue);
++ if (queue == NULL)
++ return NULL;
++
++ wl_event_queue_init(queue, display);
++
++ return queue;
++}
++
++static int
++message_count_fds(const char *signature)
++{
++ unsigned int count, i, fds = 0;
++ struct argument_details arg;
++
++ count = arg_count_for_signature(signature);
++ for (i = 0; i < count; i++) {
++ signature = get_next_argument(signature, &arg);
++ if (arg.type == 'h')
++ fds++;
++ }
++
++ return fds;
++}
++
++static struct wl_zombie *
++prepare_zombie(struct wl_proxy *proxy)
++{
++ const struct wl_interface *interface = proxy->object.interface;
++ const struct wl_message *message;
++ int i, count;
++ struct wl_zombie *zombie = NULL;
++
++ /* If we hit an event with an FD, ensure we have a zombie object and
++ * fill the fd_count slot for that event with the number of FDs for
++ * that event. Interfaces with no events containing FDs will not have
++ * zombie objects created. */
++ for (i = 0; i < interface->event_count; i++) {
++ message = &interface->events[i];
++ count = message_count_fds(message->signature);
++
++ if (!count)
++ continue;
++
++ if (!zombie) {
++ zombie = zalloc(sizeof(*zombie) +
++ (interface->event_count * sizeof(int)));
++ if (!zombie)
++ return NULL;
++
++ zombie->event_count = interface->event_count;
++ zombie->fd_count = (int *) &zombie[1];
++ }
++
++ zombie->fd_count[i] = count;
++ }
++
++ return zombie;
++}
++
++static enum wl_iterator_result
++free_zombies(void *element, void *data, uint32_t flags)
++{
++ if (flags & WL_MAP_ENTRY_ZOMBIE)
++ free(element);
++
++ return WL_ITERATOR_CONTINUE;
++}
++
++static struct wl_proxy *
++proxy_create(struct wl_proxy *factory, const struct wl_interface *interface,
++ uint32_t version)
++{
++ struct wl_proxy *proxy;
++ struct wl_display *display = factory->display;
++
++ proxy = zalloc(sizeof *proxy);
++ if (proxy == NULL)
++ return NULL;
++
++ proxy->object.interface = interface;
++ proxy->display = display;
++ proxy->queue = factory->queue;
++ proxy->refcount = 1;
++ proxy->version = version;
++
++ proxy->object.id = wl_map_insert_new(&display->objects, 0, proxy);
++ if (proxy->object.id == 0) {
++ free(proxy);
++ return NULL;
++ }
++
++ return proxy;
++}
++
++/** Create a proxy object with a given interface
++ *
++ * \param factory Factory proxy object
++ * \param interface Interface the proxy object should use
++ * \return A newly allocated proxy object or NULL on failure
++ *
++ * This function creates a new proxy object with the supplied interface. The
++ * proxy object will have an id assigned from the client id space. The id
++ * should be created on the compositor side by sending an appropriate request
++ * with \ref wl_proxy_marshal().
++ *
++ * The proxy will inherit the display and event queue of the factory object.
++ *
++ * \note This should not normally be used by non-generated code.
++ *
++ * \sa wl_display, wl_event_queue, wl_proxy_marshal()
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT struct wl_proxy *
++wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface)
++{
++ struct wl_display *display = factory->display;
++ struct wl_proxy *proxy;
++
++ pthread_mutex_lock(&display->mutex);
++ proxy = proxy_create(factory, interface, factory->version);
++ pthread_mutex_unlock(&display->mutex);
++
++ return proxy;
++}
++
++/* The caller should hold the display lock */
++static struct wl_proxy *
++wl_proxy_create_for_id(struct wl_proxy *factory,
++ uint32_t id, const struct wl_interface *interface)
++{
++ struct wl_proxy *proxy;
++ struct wl_display *display = factory->display;
++
++ proxy = zalloc(sizeof *proxy);
++ if (proxy == NULL)
++ return NULL;
++
++ proxy->object.interface = interface;
++ proxy->object.id = id;
++ proxy->display = display;
++ proxy->queue = factory->queue;
++ proxy->refcount = 1;
++ proxy->version = factory->version;
++
++ if (wl_map_insert_at(&display->objects, 0, id, proxy) == -1) {
++ free(proxy);
++ return NULL;
++ }
++
++ return proxy;
++}
++
++static void
++proxy_destroy(struct wl_proxy *proxy)
++{
++ if (proxy->flags & WL_PROXY_FLAG_ID_DELETED) {
++ wl_map_remove(&proxy->display->objects, proxy->object.id);
++ } else if (proxy->object.id < WL_SERVER_ID_START) {
++ struct wl_zombie *zombie = prepare_zombie(proxy);
++
++ /* The map now contains the zombie entry, until the delete_id
++ * event arrives. */
++ wl_map_insert_at(&proxy->display->objects,
++ WL_MAP_ENTRY_ZOMBIE,
++ proxy->object.id,
++ zombie);
++ } else {
++ wl_map_insert_at(&proxy->display->objects, 0,
++ proxy->object.id, NULL);
++ }
++
++ proxy->flags |= WL_PROXY_FLAG_DESTROYED;
++
++ wl_proxy_unref(proxy);
++}
++
++static void
++wl_proxy_destroy_caller_locks(struct wl_proxy *proxy)
++{
++ if (proxy->flags & WL_PROXY_FLAG_WRAPPER)
++ wl_abort("Tried to destroy wrapper with wl_proxy_destroy()\n");
++
++ proxy_destroy(proxy);
++}
++
++/** Destroy a proxy object
++ *
++ * \param proxy The proxy to be destroyed
++ *
++ * \c proxy must not be a proxy wrapper.
++ *
++ * \note This function will abort in response to egregious
++ * errors, and will do so with the display lock held. This means
++ * SIGABRT handlers must not perform any actions that would
++ * attempt to take that lock, or a deadlock would occur.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void
++wl_proxy_destroy(struct wl_proxy *proxy)
++{
++ struct wl_display *display = proxy->display;
++
++ pthread_mutex_lock(&display->mutex);
++
++ wl_proxy_destroy_caller_locks(proxy);
++
++ pthread_mutex_unlock(&display->mutex);
++}
++
++/** Set a proxy's listener
++ *
++ * \param proxy The proxy object
++ * \param implementation The listener to be added to proxy
++ * \param data User data to be associated with the proxy
++ * \return 0 on success or -1 on failure
++ *
++ * Set proxy's listener to \c implementation and its user data to
++ * \c data. If a listener has already been set, this function
++ * fails and nothing is changed.
++ *
++ * \c implementation is a vector of function pointers. For an opcode
++ * \c n, \c implementation[n] should point to the handler of \c n for
++ * the given object.
++ *
++ * \c proxy must not be a proxy wrapper.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT int
++wl_proxy_add_listener(struct wl_proxy *proxy,
++ void (**implementation)(void), void *data)
++{
++ if (proxy->flags & WL_PROXY_FLAG_WRAPPER)
++ wl_abort("Proxy %p is a wrapper\n", proxy);
++
++ if (proxy->object.implementation || proxy->dispatcher) {
++ wl_log("proxy %p already has listener\n", proxy);
++ return -1;
++ }
++
++ proxy->object.implementation = implementation;
++ proxy->user_data = data;
++
++ return 0;
++}
++
++/** Get a proxy's listener
++ *
++ * \param proxy The proxy object
++ * \return The address of the proxy's listener or NULL if no listener is set
++ *
++ * Gets the address to the proxy's listener; which is the listener set with
++ * \ref wl_proxy_add_listener.
++ *
++ * This function is useful in clients with multiple listeners on the same
++ * interface to allow the identification of which code to execute.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT const void *
++wl_proxy_get_listener(struct wl_proxy *proxy)
++{
++ return proxy->object.implementation;
++}
++
++/** Set a proxy's listener (with dispatcher)
++ *
++ * \param proxy The proxy object
++ * \param dispatcher The dispatcher to be used for this proxy
++ * \param implementation The dispatcher-specific listener implementation
++ * \param data User data to be associated with the proxy
++ * \return 0 on success or -1 on failure
++ *
++ * Set proxy's listener to use \c dispatcher_func as its dispatcher and \c
++ * dispatcher_data as its dispatcher-specific implementation and its user data
++ * to \c data. If a listener has already been set, this function
++ * fails and nothing is changed.
++ *
++ * The exact details of dispatcher_data depend on the dispatcher used. This
++ * function is intended to be used by language bindings, not user code.
++ *
++ * \c proxy must not be a proxy wrapper.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT int
++wl_proxy_add_dispatcher(struct wl_proxy *proxy,
++ wl_dispatcher_func_t dispatcher,
++ const void *implementation, void *data)
++{
++ if (proxy->flags & WL_PROXY_FLAG_WRAPPER)
++ wl_abort("Proxy %p is a wrapper\n", proxy);
++
++ if (proxy->object.implementation || proxy->dispatcher) {
++ wl_log("proxy %p already has listener\n", proxy);
++ return -1;
++ }
++
++ proxy->object.implementation = implementation;
++ proxy->dispatcher = dispatcher;
++ proxy->user_data = data;
++
++ return 0;
++}
++
++static struct wl_proxy *
++create_outgoing_proxy(struct wl_proxy *proxy, const struct wl_message *message,
++ union wl_argument *args,
++ const struct wl_interface *interface, uint32_t version)
++{
++ int i, count;
++ const char *signature;
++ struct argument_details arg;
++ struct wl_proxy *new_proxy = NULL;
++
++ signature = message->signature;
++ count = arg_count_for_signature(signature);
++ for (i = 0; i < count; i++) {
++ signature = get_next_argument(signature, &arg);
++
++ switch (arg.type) {
++ case 'n':
++ new_proxy = proxy_create(proxy, interface, version);
++ if (new_proxy == NULL)
++ return NULL;
++
++ args[i].o = &new_proxy->object;
++ break;
++ }
++ }
++
++ return new_proxy;
++}
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param args Extra arguments for the given request
++ * \param interface The interface to use for the new proxy
++ *
++ * This function translates a request given an opcode, an interface and a
++ * wl_argument array to the wire format and writes it to the connection
++ * buffer.
++ *
++ * For new-id arguments, this function will allocate a new wl_proxy
++ * and send the ID to the server. The new wl_proxy will be returned
++ * on success or NULL on error with errno set accordingly. The newly
++ * created proxy will inherit their version from their parent.
++ *
++ * \note This is intended to be used by language bindings and not in
++ * non-generated code.
++ *
++ * \sa wl_proxy_marshal()
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT struct wl_proxy *
++wl_proxy_marshal_array_constructor(struct wl_proxy *proxy,
++ uint32_t opcode, union wl_argument *args,
++ const struct wl_interface *interface)
++{
++ return wl_proxy_marshal_array_constructor_versioned(proxy, opcode,
++ args, interface,
++ proxy->version);
++}
++
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param args Extra arguments for the given request
++ * \param interface The interface to use for the new proxy
++ * \param version The protocol object version for the new proxy
++ *
++ * Translates the request given by opcode and the extra arguments into the
++ * wire format and write it to the connection buffer. This version takes an
++ * array of the union type wl_argument.
++ *
++ * For new-id arguments, this function will allocate a new wl_proxy
++ * and send the ID to the server. The new wl_proxy will be returned
++ * on success or NULL on error with errno set accordingly. The newly
++ * created proxy will have the version specified.
++ *
++ * \note This is intended to be used by language bindings and not in
++ * non-generated code.
++ *
++ * \sa wl_proxy_marshal()
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT struct wl_proxy *
++wl_proxy_marshal_array_constructor_versioned(struct wl_proxy *proxy,
++ uint32_t opcode,
++ union wl_argument *args,
++ const struct wl_interface *interface,
++ uint32_t version)
++{
++ return wl_proxy_marshal_array_flags(proxy, opcode, interface, version, 0, args);
++}
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param interface The interface to use for the new proxy
++ * \param version The protocol object version of the new proxy
++ * \param flags Flags that modify marshalling behaviour
++ * \param ... Extra arguments for the given request
++ * \return A new wl_proxy for the new_id argument or NULL on error
++ *
++ * Translates the request given by opcode and the extra arguments into the
++ * wire format and write it to the connection buffer.
++ *
++ * For new-id arguments, this function will allocate a new wl_proxy
++ * and send the ID to the server. The new wl_proxy will be returned
++ * on success or NULL on error with errno set accordingly. The newly
++ * created proxy will have the version specified.
++ *
++ * The flag WL_MARSHAL_FLAG_DESTROY may be passed to ensure the proxy
++ * is destroyed atomically with the marshalling in order to prevent
++ * races that can occur if the display lock is dropped between the
++ * marshal and destroy operations.
++ *
++ * \note This should not normally be used by non-generated code.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT struct wl_proxy *
++wl_proxy_marshal_flags(struct wl_proxy *proxy, uint32_t opcode,
++ const struct wl_interface *interface, uint32_t version,
++ uint32_t flags, ...)
++{
++ union wl_argument args[WL_CLOSURE_MAX_ARGS];
++ va_list ap;
++
++ va_start(ap, flags);
++ wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature,
++ args, WL_CLOSURE_MAX_ARGS, ap);
++ va_end(ap);
++
++ return wl_proxy_marshal_array_flags(proxy, opcode, interface, version, flags, args);
++}
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param interface The interface to use for the new proxy
++ * \param version The protocol object version for the new proxy
++ * \param flags Flags that modify marshalling behaviour
++ * \param args Extra arguments for the given request
++ *
++ * Translates the request given by opcode and the extra arguments into the
++ * wire format and write it to the connection buffer. This version takes an
++ * array of the union type wl_argument.
++ *
++ * For new-id arguments, this function will allocate a new wl_proxy
++ * and send the ID to the server. The new wl_proxy will be returned
++ * on success or NULL on error with errno set accordingly. The newly
++ * created proxy will have the version specified.
++ *
++ * The flag WL_MARSHAL_FLAG_DESTROY may be passed to ensure the proxy
++ * is destroyed atomically with the marshalling in order to prevent
++ * races that can occur if the display lock is dropped between the
++ * marshal and destroy operations.
++ *
++ * \note This is intended to be used by language bindings and not in
++ * non-generated code.
++ *
++ * \sa wl_proxy_marshal_flags()
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT struct wl_proxy *
++wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode,
++ const struct wl_interface *interface, uint32_t version,
++ uint32_t flags, union wl_argument *args)
++{
++ struct wl_closure *closure;
++ struct wl_proxy *new_proxy = NULL;
++ const struct wl_message *message;
++ struct wl_display *disp = proxy->display;
++
++ pthread_mutex_lock(&disp->mutex);
++
++ message = &proxy->object.interface->methods[opcode];
++ if (interface) {
++ new_proxy = create_outgoing_proxy(proxy, message,
++ args, interface,
++ version);
++ if (new_proxy == NULL)
++ goto err_unlock;
++ }
++
++ if (proxy->display->last_error) {
++ goto err_unlock;
++ }
++
++ closure = wl_closure_marshal(&proxy->object, opcode, args, message);
++ if (closure == NULL) {
++ wl_log("Error marshalling request: %s\n", strerror(errno));
++ display_fatal_error(proxy->display, errno);
++ goto err_unlock;
++ }
++
++ if (debug_client)
++ wl_closure_print(closure, &proxy->object, true, false, NULL);
++
++ if (wl_closure_send(closure, proxy->display->connection)) {
++ wl_log("Error sending request: %s\n", strerror(errno));
++ display_fatal_error(proxy->display, errno);
++ }
++
++ wl_closure_destroy(closure);
++
++ err_unlock:
++ if (flags & WL_MARSHAL_FLAG_DESTROY)
++ wl_proxy_destroy_caller_locks(proxy);
++
++ pthread_mutex_unlock(&disp->mutex);
++
++ return new_proxy;
++}
++
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param ... Extra arguments for the given request
++ *
++ * This function is similar to wl_proxy_marshal_constructor(), except
++ * it doesn't create proxies for new-id arguments.
++ *
++ * \note This should not normally be used by non-generated code.
++ *
++ * \sa wl_proxy_create()
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void
++wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
++{
++ union wl_argument args[WL_CLOSURE_MAX_ARGS];
++ va_list ap;
++
++ va_start(ap, opcode);
++ wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature,
++ args, WL_CLOSURE_MAX_ARGS, ap);
++ va_end(ap);
++
++ wl_proxy_marshal_array_constructor(proxy, opcode, args, NULL);
++}
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param interface The interface to use for the new proxy
++ * \param ... Extra arguments for the given request
++ * \return A new wl_proxy for the new_id argument or NULL on error
++ *
++ * This function translates a request given an opcode, an interface and extra
++ * arguments to the wire format and writes it to the connection buffer. The
++ * types of the extra arguments must correspond to the argument types of the
++ * method associated with the opcode in the interface.
++ *
++ * For new-id arguments, this function will allocate a new wl_proxy
++ * and send the ID to the server. The new wl_proxy will be returned
++ * on success or NULL on error with errno set accordingly. The newly
++ * created proxy will inherit their version from their parent.
++ *
++ * \note This should not normally be used by non-generated code.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT struct wl_proxy *
++wl_proxy_marshal_constructor(struct wl_proxy *proxy, uint32_t opcode,
++ const struct wl_interface *interface, ...)
++{
++ union wl_argument args[WL_CLOSURE_MAX_ARGS];
++ va_list ap;
++
++ va_start(ap, interface);
++ wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature,
++ args, WL_CLOSURE_MAX_ARGS, ap);
++ va_end(ap);
++
++ return wl_proxy_marshal_array_constructor(proxy, opcode,
++ args, interface);
++}
++
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param interface The interface to use for the new proxy
++ * \param version The protocol object version of the new proxy
++ * \param ... Extra arguments for the given request
++ * \return A new wl_proxy for the new_id argument or NULL on error
++ *
++ * Translates the request given by opcode and the extra arguments into the
++ * wire format and write it to the connection buffer.
++ *
++ * For new-id arguments, this function will allocate a new wl_proxy
++ * and send the ID to the server. The new wl_proxy will be returned
++ * on success or NULL on error with errno set accordingly. The newly
++ * created proxy will have the version specified.
++ *
++ * \note This should not normally be used by non-generated code.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT struct wl_proxy *
++wl_proxy_marshal_constructor_versioned(struct wl_proxy *proxy, uint32_t opcode,
++ const struct wl_interface *interface,
++ uint32_t version, ...)
++{
++ union wl_argument args[WL_CLOSURE_MAX_ARGS];
++ va_list ap;
++
++ va_start(ap, version);
++ wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature,
++ args, WL_CLOSURE_MAX_ARGS, ap);
++ va_end(ap);
++
++ return wl_proxy_marshal_array_constructor_versioned(proxy, opcode,
++ args, interface,
++ version);
++}
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param args Extra arguments for the given request
++ *
++ * This function is similar to wl_proxy_marshal_array_constructor(), except
++ * it doesn't create proxies for new-id arguments.
++ *
++ * \note This is intended to be used by language bindings and not in
++ * non-generated code.
++ *
++ * \sa wl_proxy_marshal()
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void
++wl_proxy_marshal_array(struct wl_proxy *proxy, uint32_t opcode,
++ union wl_argument *args)
++{
++ wl_proxy_marshal_array_constructor(proxy, opcode, args, NULL);
++}
++
++static void
++display_handle_error(void *data,
++ struct wl_display *display, void *object,
++ uint32_t code, const char *message)
++{
++ struct wl_proxy *proxy = object;
++ uint32_t object_id;
++ const struct wl_interface *interface;
++
++ if (proxy) {
++ wl_log("%s@%u: error %d: %s\n",
++ proxy->object.interface->name,
++ proxy->object.id,
++ code, message);
++
++ object_id = proxy->object.id;
++ interface = proxy->object.interface;
++ } else {
++ wl_log("[destroyed object]: error %d: %s\n",
++ code, message);
++
++ object_id = 0;
++ interface = NULL;
++ }
++
++ display_protocol_error(display, code, object_id, interface);
++}
++
++static void
++display_handle_delete_id(void *data, struct wl_display *display, uint32_t id)
++{
++ struct wl_proxy *proxy;
++
++ pthread_mutex_lock(&display->mutex);
++
++ proxy = wl_map_lookup(&display->objects, id);
++
++ if (wl_object_is_zombie(&display->objects, id)) {
++ /* For zombie objects, the 'proxy' is actually the zombie
++ * event-information structure, which we can free. */
++ free(proxy);
++ wl_map_remove(&display->objects, id);
++ } else if (proxy) {
++ proxy->flags |= WL_PROXY_FLAG_ID_DELETED;
++ } else {
++ wl_log("error: received delete_id for unknown id (%u)\n", id);
++ }
++
++ pthread_mutex_unlock(&display->mutex);
++}
++
++static const struct wl_display_listener display_listener = {
++ display_handle_error,
++ display_handle_delete_id
++};
++
++static int
++connect_to_socket(const char *name)
++{
++ struct sockaddr_un addr;
++ socklen_t size;
++ const char *runtime_dir;
++ int name_size, fd;
++ bool path_is_absolute;
++
++ if (name == NULL)
++ name = getenv("WAYLAND_DISPLAY");
++ if (name == NULL)
++ name = "wayland-0";
++
++ path_is_absolute = name[0] == '/';
++
++ runtime_dir = getenv("XDG_RUNTIME_DIR");
++ if (((!runtime_dir || runtime_dir[0] != '/') && !path_is_absolute)) {
++ wl_log("error: XDG_RUNTIME_DIR is invalid or not set in the environment.\n");
++ /* to prevent programs reporting
++ * "failed to create display: Success" */
++ errno = ENOENT;
++ return -1;
++ }
++
++ fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
++ if (fd < 0)
++ return -1;
++
++ memset(&addr, 0, sizeof addr);
++ addr.sun_family = AF_LOCAL;
++ if (!path_is_absolute) {
++ name_size =
++ snprintf(addr.sun_path, sizeof addr.sun_path,
++ "%s/%s", runtime_dir, name) + 1;
++ } else {
++ /* absolute path */
++ name_size =
++ snprintf(addr.sun_path, sizeof addr.sun_path,
++ "%s", name) + 1;
++ }
++
++ assert(name_size > 0);
++ if (name_size > (int)sizeof addr.sun_path) {
++ if (!path_is_absolute) {
++ wl_log("error: socket path \"%s/%s\" plus null terminator"
++ " exceeds %i bytes\n", runtime_dir, name, (int) sizeof(addr.sun_path));
++ } else {
++ wl_log("error: socket path \"%s\" plus null terminator"
++ " exceeds %i bytes\n", name, (int) sizeof(addr.sun_path));
++ }
++ close(fd);
++ /* to prevent programs reporting
++ * "failed to add socket: Success" */
++ errno = ENAMETOOLONG;
++ return -1;
++ };
++
++ size = offsetof (struct sockaddr_un, sun_path) + name_size;
++
++ if (connect(fd, (struct sockaddr *) &addr, size) < 0) {
++ close(fd);
++ return -1;
++ }
++
++ return fd;
++}
++
++/** Connect to Wayland display on an already open fd
++ *
++ * \param fd The fd to use for the connection
++ * \return A \ref wl_display object or \c NULL on failure
++ *
++ * The wl_display takes ownership of the fd and will close it when the
++ * display is destroyed. The fd will also be closed in case of
++ * failure.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT struct wl_display *
++wl_display_connect_to_fd(int fd)
++{
++ struct wl_display *display;
++ const char *debug;
++
++ debug = getenv("WAYLAND_DEBUG");
++ if (debug && (strstr(debug, "client") || strstr(debug, "1")))
++ debug_client = 1;
++
++ display = zalloc(sizeof *display);
++ if (display == NULL) {
++ close(fd);
++ return NULL;
++ }
++
++ display->fd = fd;
++ wl_map_init(&display->objects, WL_MAP_CLIENT_SIDE);
++ wl_event_queue_init(&display->default_queue, display);
++ wl_event_queue_init(&display->display_queue, display);
++ pthread_mutex_init(&display->mutex, NULL);
++ pthread_cond_init(&display->reader_cond, NULL);
++ display->reader_count = 0;
++
++ if (wl_map_insert_at(&display->objects, 0, 0, NULL) == -1)
++ goto err_connection;
++
++ display->proxy.object.id =
++ wl_map_insert_new(&display->objects, 0, display);
++
++ if (display->proxy.object.id == 0)
++ goto err_connection;
++
++ display->proxy.object.interface = &wl_display_interface;
++ display->proxy.display = display;
++ display->proxy.object.implementation = (void(**)(void)) &display_listener;
++ display->proxy.user_data = display;
++ display->proxy.queue = &display->default_queue;
++ display->proxy.flags = 0;
++ display->proxy.refcount = 1;
++
++ /* We set this version to 0 for backwards compatibility.
++ *
++ * If a client is using old versions of protocol headers,
++ * it will use unversioned API to create proxies. Those
++ * proxies will inherit this 0.
++ *
++ * A client could be passing these proxies into library
++ * code newer than the headers that checks proxy
++ * versions. When the proxy version is reported as 0
++ * the library will know that it can't reliably determine
++ * the proxy version, and should do whatever fallback is
++ * required.
++ *
++ * This trick forces wl_display to always report 0, but
++ * since it's a special object that we can't bind
++ * specific versions of anyway, this should be fine.
++ */
++ display->proxy.version = 0;
++
++ display->connection = wl_connection_create(display->fd);
++ if (display->connection == NULL)
++ goto err_connection;
++
++ return display;
++
++ err_connection:
++ pthread_mutex_destroy(&display->mutex);
++ pthread_cond_destroy(&display->reader_cond);
++ wl_map_release(&display->objects);
++ close(display->fd);
++ free(display);
++
++ return NULL;
++}
++
++/** Connect to a Wayland display
++ *
++ * \param name Name of the Wayland display to connect to
++ * \return A \ref wl_display object or \c NULL on failure
++ *
++ * Connect to the Wayland display named \c name. If \c name is \c NULL,
++ * its value will be replaced with the WAYLAND_DISPLAY environment
++ * variable if it is set, otherwise display "wayland-0" will be used.
++ *
++ * If WAYLAND_SOCKET is set, it's interpreted as a file descriptor number
++ * referring to an already opened socket. In this case, the socket is used
++ * as-is and \c name is ignored.
++ *
++ * If \c name is a relative path, then the socket is opened relative to
++ * the XDG_RUNTIME_DIR directory.
++ *
++ * If \c name is an absolute path, then that path is used as-is for
++ * the location of the socket at which the Wayland server is listening;
++ * no qualification inside XDG_RUNTIME_DIR is attempted.
++ *
++ * If \c name is \c NULL and the WAYLAND_DISPLAY environment variable
++ * is set to an absolute pathname, then that pathname is used as-is
++ * for the socket in the same manner as if \c name held an absolute
++ * path. Support for absolute paths in \c name and WAYLAND_DISPLAY
++ * is present since Wayland version 1.15.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT struct wl_display *
++wl_display_connect(const char *name)
++{
++ char *connection, *end;
++ int flags, fd;
++
++ connection = getenv("WAYLAND_SOCKET");
++ if (connection) {
++ int prev_errno = errno;
++ errno = 0;
++ fd = strtol(connection, &end, 10);
++ if (errno != 0 || connection == end || *end != '\0')
++ return NULL;
++ errno = prev_errno;
++
++ flags = fcntl(fd, F_GETFD);
++ if (flags == -1 && errno == EBADF)
++ return NULL;
++ else if (flags != -1)
++ fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
++ unsetenv("WAYLAND_SOCKET");
++ } else {
++ fd = connect_to_socket(name);
++ if (fd < 0)
++ return NULL;
++ }
++
++ return wl_display_connect_to_fd(fd);
++}
++
++/** Close a connection to a Wayland display
++ *
++ * \param display The display context object
++ *
++ * Close the connection to \c display and free all resources associated
++ * with it.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT void
++wl_display_disconnect(struct wl_display *display)
++{
++ wl_connection_destroy(display->connection);
++ wl_map_for_each(&display->objects, free_zombies, NULL);
++ wl_map_release(&display->objects);
++ wl_event_queue_release(&display->default_queue);
++ wl_event_queue_release(&display->display_queue);
++ pthread_mutex_destroy(&display->mutex);
++ pthread_cond_destroy(&display->reader_cond);
++ close(display->fd);
++
++ free(display);
++}
++
++/** Get a display context's file descriptor
++ *
++ * \param display The display context object
++ * \return Display object file descriptor
++ *
++ * Return the file descriptor associated with a display so it can be
++ * integrated into the client's main loop.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_get_fd(struct wl_display *display)
++{
++ return display->fd;
++}
++
++static void
++sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
++{
++ int *done = data;
++
++ *done = 1;
++ wl_callback_destroy(callback);
++}
++
++static const struct wl_callback_listener sync_listener = {
++ sync_callback
++};
++
++/** Block until all pending request are processed by the server
++ *
++ * \param display The display context object
++ * \param queue The queue on which to run the roundtrip
++ * \return The number of dispatched events on success or -1 on failure
++ *
++ * This function blocks until the server has processed all currently issued
++ * requests by sending a request to the display server and waiting for a
++ * reply before returning.
++ *
++ * This function uses wl_display_dispatch_queue() internally. It is not allowed
++ * to call this function while the thread is being prepared for reading events,
++ * and doing so will cause a dead lock.
++ *
++ * \note This function may dispatch other events being received on the given
++ * queue.
++ *
++ * \sa wl_display_roundtrip()
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_roundtrip_queue(struct wl_display *display, struct wl_event_queue *queue)
++{
++ struct wl_display *display_wrapper;
++ struct wl_callback *callback;
++ int done, ret = 0;
++
++ done = 0;
++
++ display_wrapper = wl_proxy_create_wrapper(display);
++ if (!display_wrapper)
++ return -1;
++
++ wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue);
++ callback = wl_display_sync(display_wrapper);
++ wl_proxy_wrapper_destroy(display_wrapper);
++
++ if (callback == NULL)
++ return -1;
++
++ wl_callback_add_listener(callback, &sync_listener, &done);
++ while (!done && ret >= 0)
++ ret = wl_display_dispatch_queue(display, queue);
++
++ if (ret == -1 && !done)
++ wl_callback_destroy(callback);
++
++ return ret;
++}
++
++/** Block until all pending request are processed by the server
++ *
++ * \param display The display context object
++ * \return The number of dispatched events on success or -1 on failure
++ *
++ * This function blocks until the server has processed all currently issued
++ * requests by sending a request to the display server and waiting for a reply
++ * before returning.
++ *
++ * This function uses wl_display_dispatch_queue() internally. It is not allowed
++ * to call this function while the thread is being prepared for reading events,
++ * and doing so will cause a dead lock.
++ *
++ * \note This function may dispatch other events being received on the default
++ * queue.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_roundtrip(struct wl_display *display)
++{
++ return wl_display_roundtrip_queue(display, &display->default_queue);
++}
++
++static int
++create_proxies(struct wl_proxy *sender, struct wl_closure *closure)
++{
++ struct wl_proxy *proxy;
++ const char *signature;
++ struct argument_details arg;
++ uint32_t id;
++ int i;
++ int count;
++
++ signature = closure->message->signature;
++ count = arg_count_for_signature(signature);
++ for (i = 0; i < count; i++) {
++ signature = get_next_argument(signature, &arg);
++ switch (arg.type) {
++ case 'n':
++ id = closure->args[i].n;
++ if (id == 0) {
++ closure->args[i].o = NULL;
++ break;
++ }
++ proxy = wl_proxy_create_for_id(sender, id,
++ closure->message->types[i]);
++ if (proxy == NULL)
++ return -1;
++ closure->args[i].o = (struct wl_object *)proxy;
++ break;
++ default:
++ break;
++ }
++ }
++
++ return 0;
++}
++
++static void
++increase_closure_args_refcount(struct wl_closure *closure)
++{
++ const char *signature;
++ struct argument_details arg;
++ int i, count;
++ struct wl_proxy *proxy;
++
++ signature = closure->message->signature;
++ count = arg_count_for_signature(signature);
++ for (i = 0; i < count; i++) {
++ signature = get_next_argument(signature, &arg);
++ switch (arg.type) {
++ case 'n':
++ case 'o':
++ proxy = (struct wl_proxy *) closure->args[i].o;
++ if (proxy)
++ proxy->refcount++;
++ break;
++ default:
++ break;
++ }
++ }
++
++ closure->proxy->refcount++;
++}
++
++static int
++queue_event(struct wl_display *display, int len)
++{
++ uint32_t p[2], id;
++ int opcode, size;
++ struct wl_proxy *proxy;
++ struct wl_closure *closure;
++ const struct wl_message *message;
++ struct wl_event_queue *queue;
++ struct timespec tp;
++ unsigned int time;
++ int num_zombie_fds;
++
++ wl_connection_copy(display->connection, p, sizeof p);
++ id = p[0];
++ opcode = p[1] & 0xffff;
++ size = p[1] >> 16;
++ if (len < size)
++ return 0;
++
++ /* If our proxy is gone or a zombie, just eat the event (and any FDs,
++ * if applicable). */
++ proxy = wl_map_lookup(&display->objects, id);
++ if (!proxy || wl_object_is_zombie(&display->objects, id)) {
++ struct wl_zombie *zombie = wl_map_lookup(&display->objects, id);
++ num_zombie_fds = (zombie && opcode < zombie->event_count) ?
++ zombie->fd_count[opcode] : 0;
++
++ if (debug_client) {
++ clock_gettime(CLOCK_REALTIME, &tp);
++ time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
++
++ fprintf(stderr, "[%7u.%03u] discarded [%s]@%d.[event %d]"
++ "(%d fd, %d byte)\n",
++ time / 1000, time % 1000,
++ zombie ? "zombie" : "unknown",
++ id, opcode,
++ num_zombie_fds, size);
++ }
++ if (num_zombie_fds > 0)
++ wl_connection_close_fds_in(display->connection,
++ num_zombie_fds);
++
++ wl_connection_consume(display->connection, size);
++ return size;
++ }
++
++ if (opcode >= proxy->object.interface->event_count) {
++ wl_log("interface '%s' has no event %u\n",
++ proxy->object.interface->name, opcode);
++ return -1;
++ }
++
++ message = &proxy->object.interface->events[opcode];
++ closure = wl_connection_demarshal(display->connection, size,
++ &display->objects, message);
++ if (!closure)
++ return -1;
++
++ if (create_proxies(proxy, closure) < 0) {
++ wl_closure_destroy(closure);
++ return -1;
++ }
++
++ if (wl_closure_lookup_objects(closure, &display->objects) != 0) {
++ wl_closure_destroy(closure);
++ return -1;
++ }
++
++ closure->proxy = proxy;
++ increase_closure_args_refcount(closure);
++
++ if (proxy == &display->proxy)
++ queue = &display->display_queue;
++ else
++ queue = proxy->queue;
++
++ wl_list_insert(queue->event_list.prev, &closure->link);
++
++ return size;
++}
++
++static uint32_t
++id_from_object(union wl_argument *arg)
++{
++ struct wl_proxy *proxy;
++
++ if (arg->o) {
++ proxy = (struct wl_proxy *)arg->o;
++ return proxy->object.id;
++ }
++
++ return 0;
++}
++
++static void
++dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
++{
++ struct wl_closure *closure;
++ struct wl_proxy *proxy;
++ int opcode;
++ bool proxy_destroyed;
++
++ closure = wl_container_of(queue->event_list.next, closure, link);
++ wl_list_remove(&closure->link);
++ opcode = closure->opcode;
++
++ /* Verify that the receiving object is still valid by checking if has
++ * been destroyed by the application. */
++ validate_closure_objects(closure);
++ proxy = closure->proxy;
++ proxy_destroyed = !!(proxy->flags & WL_PROXY_FLAG_DESTROYED);
++ if (proxy_destroyed) {
++ if (debug_client)
++ wl_closure_print(closure, &proxy->object, false, true, id_from_object);
++ destroy_queued_closure(closure);
++ return;
++ }
++
++ pthread_mutex_unlock(&display->mutex);
++
++ if (proxy->dispatcher) {
++ if (debug_client)
++ wl_closure_print(closure, &proxy->object, false, false, id_from_object);
++
++ wl_closure_dispatch(closure, proxy->dispatcher,
++ &proxy->object, opcode);
++ } else if (proxy->object.implementation) {
++ if (debug_client)
++ wl_closure_print(closure, &proxy->object, false, false, id_from_object);
++
++ wl_closure_invoke(closure, WL_CLOSURE_INVOKE_CLIENT,
++ &proxy->object, opcode, proxy->user_data);
++ }
++
++ pthread_mutex_lock(&display->mutex);
++
++ destroy_queued_closure(closure);
++}
++
++static int
++read_events(struct wl_display *display)
++{
++ int total, rem, size;
++ uint32_t serial;
++
++ display->reader_count--;
++ if (display->reader_count == 0) {
++ total = wl_connection_read(display->connection);
++ if (total == -1) {
++ if (errno == EAGAIN) {
++ /* we must wake up threads whenever
++ * the reader_count dropped to 0 */
++ display_wakeup_threads(display);
++
++ return 0;
++ }
++
++ display_fatal_error(display, errno);
++ return -1;
++ } else if (total == 0) {
++ /* The compositor has closed the socket. This
++ * should be considered an error so we'll fake
++ * an errno */
++ errno = EPIPE;
++ display_fatal_error(display, errno);
++ return -1;
++ }
++
++ for (rem = total; rem >= 8; rem -= size) {
++ size = queue_event(display, rem);
++ if (size == -1) {
++ display_fatal_error(display, errno);
++ return -1;
++ } else if (size == 0) {
++ break;
++ }
++ }
++
++ display_wakeup_threads(display);
++ } else {
++ serial = display->read_serial;
++ while (display->read_serial == serial)
++ pthread_cond_wait(&display->reader_cond,
++ &display->mutex);
++
++ if (display->last_error) {
++ errno = display->last_error;
++ return -1;
++ }
++ }
++
++ return 0;
++}
++
++static void
++cancel_read(struct wl_display *display)
++{
++ display->reader_count--;
++ if (display->reader_count == 0)
++ display_wakeup_threads(display);
++}
++
++/** Read events from display file descriptor
++ *
++ * \param display The display context object
++ * \return 0 on success or -1 on error. In case of error errno will
++ * be set accordingly
++ *
++ * Calling this function will result in data available on the display file
++ * descriptor being read and read events will be queued on their corresponding
++ * event queues.
++ *
++ * Before calling this function, depending on what thread it is to be called
++ * from, wl_display_prepare_read_queue() or wl_display_prepare_read() needs to
++ * be called. See wl_display_prepare_read_queue() for more details.
++ *
++ * When being called at a point where other threads have been prepared to read
++ * (using wl_display_prepare_read_queue() or wl_display_prepare_read()) this
++ * function will sleep until all other prepared threads have either been
++ * cancelled (using wl_display_cancel_read()) or them self entered this
++ * function. The last thread that calls this function will then read and queue
++ * events on their corresponding event queues, and finally wake up all other
++ * wl_display_read_events() calls causing them to return.
++ *
++ * If a thread cancels a read preparation when all other threads that have
++ * prepared to read has either called wl_display_cancel_read() or
++ * wl_display_read_events(), all reader threads will return without having read
++ * any data.
++ *
++ * To dispatch events that may have been queued, call
++ * wl_display_dispatch_pending() or wl_display_dispatch_queue_pending().
++ *
++ * \sa wl_display_prepare_read(), wl_display_cancel_read(),
++ * wl_display_dispatch_pending(), wl_display_dispatch()
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_read_events(struct wl_display *display)
++{
++ int ret;
++
++ pthread_mutex_lock(&display->mutex);
++
++ if (display->last_error) {
++ cancel_read(display);
++ pthread_mutex_unlock(&display->mutex);
++
++ errno = display->last_error;
++ return -1;
++ }
++
++ ret = read_events(display);
++
++ pthread_mutex_unlock(&display->mutex);
++
++ return ret;
++}
++
++static int
++dispatch_queue(struct wl_display *display, struct wl_event_queue *queue)
++{
++ int count;
++
++ if (display->last_error)
++ goto err;
++
++ count = 0;
++ while (!wl_list_empty(&display->display_queue.event_list)) {
++ dispatch_event(display, &display->display_queue);
++ if (display->last_error)
++ goto err;
++ count++;
++ }
++
++ while (!wl_list_empty(&queue->event_list)) {
++ dispatch_event(display, queue);
++ if (display->last_error)
++ goto err;
++ count++;
++ }
++
++ return count;
++
++err:
++ errno = display->last_error;
++
++ return -1;
++}
++
++/** Prepare to read events from the display's file descriptor to a queue
++ *
++ * \param display The display context object
++ * \param queue The event queue to use
++ * \return 0 on success or -1 if event queue was not empty
++ *
++ * This function (or wl_display_prepare_read()) must be called before reading
++ * from the file descriptor using wl_display_read_events(). Calling
++ * wl_display_prepare_read_queue() announces the calling thread's intention to
++ * read and ensures that until the thread is ready to read and calls
++ * wl_display_read_events(), no other thread will read from the file descriptor.
++ * This only succeeds if the event queue is empty, and if not -1 is returned and
++ * errno set to EAGAIN.
++ *
++ * If a thread successfully calls wl_display_prepare_read_queue(), it must
++ * either call wl_display_read_events() when it's ready or cancel the read
++ * intention by calling wl_display_cancel_read().
++ *
++ * Use this function before polling on the display fd or integrate the fd into a
++ * toolkit event loop in a race-free way. A correct usage would be (with most
++ * error checking left out):
++ *
++ * \code
++ * while (wl_display_prepare_read_queue(display, queue) != 0)
++ * wl_display_dispatch_queue_pending(display, queue);
++ * wl_display_flush(display);
++ *
++ * ret = poll(fds, nfds, -1);
++ * if (has_error(ret))
++ * wl_display_cancel_read(display);
++ * else
++ * wl_display_read_events(display);
++ *
++ * wl_display_dispatch_queue_pending(display, queue);
++ * \endcode
++ *
++ * Here we call wl_display_prepare_read_queue(), which ensures that between
++ * returning from that call and eventually calling wl_display_read_events(), no
++ * other thread will read from the fd and queue events in our queue. If the call
++ * to wl_display_prepare_read_queue() fails, we dispatch the pending events and
++ * try again until we're successful.
++ *
++ * The wl_display_prepare_read_queue() function doesn't acquire exclusive access
++ * to the display's fd. It only registers that the thread calling this function
++ * has intention to read from fd. When all registered readers call
++ * wl_display_read_events(), only one (at random) eventually reads and queues
++ * the events and the others are sleeping meanwhile. This way we avoid races and
++ * still can read from more threads.
++ *
++ * \sa wl_display_cancel_read(), wl_display_read_events(),
++ * wl_display_prepare_read()
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_prepare_read_queue(struct wl_display *display,
++ struct wl_event_queue *queue)
++{
++ int ret;
++
++ pthread_mutex_lock(&display->mutex);
++
++ if (!wl_list_empty(&queue->event_list)) {
++ errno = EAGAIN;
++ ret = -1;
++ } else {
++ display->reader_count++;
++ ret = 0;
++ }
++
++ pthread_mutex_unlock(&display->mutex);
++
++ return ret;
++}
++
++/** Prepare to read events from the display's file descriptor
++ *
++ * \param display The display context object
++ * \return 0 on success or -1 if event queue was not empty
++ *
++ * This function does the same thing as wl_display_prepare_read_queue()
++ * with the default queue passed as the queue.
++ *
++ * \sa wl_display_prepare_read_queue
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_prepare_read(struct wl_display *display)
++{
++ return wl_display_prepare_read_queue(display, &display->default_queue);
++}
++
++/** Cancel read intention on display's fd
++ *
++ * \param display The display context object
++ *
++ * After a thread successfully called wl_display_prepare_read() it must
++ * either call wl_display_read_events() or wl_display_cancel_read().
++ * If the threads do not follow this rule it will lead to deadlock.
++ *
++ * \sa wl_display_prepare_read(), wl_display_read_events()
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT void
++wl_display_cancel_read(struct wl_display *display)
++{
++ pthread_mutex_lock(&display->mutex);
++
++ cancel_read(display);
++
++ pthread_mutex_unlock(&display->mutex);
++}
++
++static int
++wl_display_poll(struct wl_display *display, short int events)
++{
++ int ret;
++ struct pollfd pfd[1];
++
++ pfd[0].fd = display->fd;
++ pfd[0].events = events;
++ do {
++ ret = poll(pfd, 1, -1);
++ } while (ret == -1 && errno == EINTR);
++
++ return ret;
++}
++
++/** Dispatch events in an event queue
++ *
++ * \param display The display context object
++ * \param queue The event queue to dispatch
++ * \return The number of dispatched events on success or -1 on failure
++ *
++ * Dispatch events on the given event queue.
++ *
++ * If the given event queue is empty, this function blocks until there are
++ * events to be read from the display fd. Events are read and queued on
++ * the appropriate event queues. Finally, events on given event queue are
++ * dispatched. On failure -1 is returned and errno set appropriately.
++ *
++ * In a multi threaded environment, do not manually wait using poll() (or
++ * equivalent) before calling this function, as doing so might cause a dead
++ * lock. If external reliance on poll() (or equivalent) is required, see
++ * wl_display_prepare_read_queue() of how to do so.
++ *
++ * This function is thread safe as long as it dispatches the right queue on the
++ * right thread. It is also compatible with the multi thread event reading
++ * preparation API (see wl_display_prepare_read_queue()), and uses the
++ * equivalent functionality internally. It is not allowed to call this function
++ * while the thread is being prepared for reading events, and doing so will
++ * cause a dead lock.
++ *
++ * It can be used as a helper function to ease the procedure of reading and
++ * dispatching events.
++ *
++ * \note Since Wayland 1.5 the display has an extra queue
++ * for its own events (i. e. delete_id). This queue is dispatched always,
++ * no matter what queue we passed as an argument to this function.
++ * That means that this function can return non-0 value even when it
++ * haven't dispatched any event for the given queue.
++ *
++ * \sa wl_display_dispatch(), wl_display_dispatch_pending(),
++ * wl_display_dispatch_queue_pending(), wl_display_prepare_read_queue()
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_dispatch_queue(struct wl_display *display,
++ struct wl_event_queue *queue)
++{
++ int ret;
++
++ if (wl_display_prepare_read_queue(display, queue) == -1)
++ return wl_display_dispatch_queue_pending(display, queue);
++
++ while (true) {
++ ret = wl_display_flush(display);
++
++ if (ret != -1 || errno != EAGAIN)
++ break;
++
++ if (wl_display_poll(display, POLLOUT) == -1) {
++ wl_display_cancel_read(display);
++ return -1;
++ }
++ }
++
++ /* Don't stop if flushing hits an EPIPE; continue so we can read any
++ * protocol error that may have triggered it. */
++ if (ret < 0 && errno != EPIPE) {
++ wl_display_cancel_read(display);
++ return -1;
++ }
++
++ if (wl_display_poll(display, POLLIN) == -1) {
++ wl_display_cancel_read(display);
++ return -1;
++ }
++
++ if (wl_display_read_events(display) == -1)
++ return -1;
++
++ return wl_display_dispatch_queue_pending(display, queue);
++}
++
++/** Dispatch pending events in an event queue
++ *
++ * \param display The display context object
++ * \param queue The event queue to dispatch
++ * \return The number of dispatched events on success or -1 on failure
++ *
++ * Dispatch all incoming events for objects assigned to the given
++ * event queue. On failure -1 is returned and errno set appropriately.
++ * If there are no events queued, this function returns immediately.
++ *
++ * \memberof wl_display
++ * \since 1.0.2
++ */
++WL_EXPORT int
++wl_display_dispatch_queue_pending(struct wl_display *display,
++ struct wl_event_queue *queue)
++{
++ int ret;
++
++ pthread_mutex_lock(&display->mutex);
++
++ ret = dispatch_queue(display, queue);
++
++ pthread_mutex_unlock(&display->mutex);
++
++ return ret;
++}
++
++/** Process incoming events
++ *
++ * \param display The display context object
++ * \return The number of dispatched events on success or -1 on failure
++ *
++ * Dispatch events on the default event queue.
++ *
++ * If the default event queue is empty, this function blocks until there are
++ * events to be read from the display fd. Events are read and queued on
++ * the appropriate event queues. Finally, events on the default event queue
++ * are dispatched. On failure -1 is returned and errno set appropriately.
++ *
++ * In a multi threaded environment, do not manually wait using poll() (or
++ * equivalent) before calling this function, as doing so might cause a dead
++ * lock. If external reliance on poll() (or equivalent) is required, see
++ * wl_display_prepare_read_queue() of how to do so.
++ *
++ * This function is thread safe as long as it dispatches the right queue on the
++ * right thread. It is also compatible with the multi thread event reading
++ * preparation API (see wl_display_prepare_read_queue()), and uses the
++ * equivalent functionality internally. It is not allowed to call this function
++ * while the thread is being prepared for reading events, and doing so will
++ * cause a dead lock.
++ *
++ * \note It is not possible to check if there are events on the queue
++ * or not. For dispatching default queue events without blocking, see \ref
++ * wl_display_dispatch_pending().
++ *
++ * \sa wl_display_dispatch_pending(), wl_display_dispatch_queue(),
++ * wl_display_read_events()
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_dispatch(struct wl_display *display)
++{
++ return wl_display_dispatch_queue(display, &display->default_queue);
++}
++
++/** Dispatch default queue events without reading from the display fd
++ *
++ * \param display The display context object
++ * \return The number of dispatched events or -1 on failure
++ *
++ * This function dispatches events on the main event queue. It does not
++ * attempt to read the display fd and simply returns zero if the main
++ * queue is empty, i.e., it doesn't block.
++ *
++ * \sa wl_display_dispatch(), wl_display_dispatch_queue(),
++ * wl_display_flush()
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_dispatch_pending(struct wl_display *display)
++{
++ return wl_display_dispatch_queue_pending(display,
++ &display->default_queue);
++}
++
++/** Retrieve the last error that occurred on a display
++ *
++ * \param display The display context object
++ * \return The last error that occurred on \c display or 0 if no error occurred
++ *
++ * Return the last error that occurred on the display. This may be an error sent
++ * by the server or caused by the local client.
++ *
++ * \note Errors are \b fatal. If this function returns non-zero the display
++ * can no longer be used.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_get_error(struct wl_display *display)
++{
++ int ret;
++
++ pthread_mutex_lock(&display->mutex);
++
++ ret = display->last_error;
++
++ pthread_mutex_unlock(&display->mutex);
++
++ return ret;
++}
++
++/** Retrieves the information about a protocol error:
++ *
++ * \param display The Wayland display
++ * \param interface if not NULL, stores the interface where the error occurred,
++ * or NULL, if unknown.
++ * \param id if not NULL, stores the object id that generated
++ * the error, or 0, if the object id is unknown. There's no
++ * guarantee the object is still valid; the client must know
++ * if it deleted the object.
++ * \return The error code as defined in the interface specification.
++ *
++ * \code
++ * int err = wl_display_get_error(display);
++ *
++ * if (err == EPROTO) {
++ * code = wl_display_get_protocol_error(display, &interface, &id);
++ * handle_error(code, interface, id);
++ * }
++ *
++ * ...
++ * \endcode
++ * \memberof wl_display
++ */
++WL_EXPORT uint32_t
++wl_display_get_protocol_error(struct wl_display *display,
++ const struct wl_interface **interface,
++ uint32_t *id)
++{
++ uint32_t ret;
++
++ pthread_mutex_lock(&display->mutex);
++
++ ret = display->protocol_error.code;
++
++ if (interface)
++ *interface = display->protocol_error.interface;
++ if (id)
++ *id = display->protocol_error.id;
++
++ pthread_mutex_unlock(&display->mutex);
++
++ return ret;
++}
++
++
++/** Send all buffered requests on the display to the server
++ *
++ * \param display The display context object
++ * \return The number of bytes sent on success or -1 on failure
++ *
++ * Send all buffered data on the client side to the server. Clients should
++ * always call this function before blocking on input from the display fd.
++ * On success, the number of bytes sent to the server is returned. On
++ * failure, this function returns -1 and errno is set appropriately.
++ *
++ * wl_display_flush() never blocks. It will write as much data as
++ * possible, but if all data could not be written, errno will be set
++ * to EAGAIN and -1 returned. In that case, use poll on the display
++ * file descriptor to wait for it to become writable again.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_flush(struct wl_display *display)
++{
++ int ret;
++
++ pthread_mutex_lock(&display->mutex);
++
++ if (display->last_error) {
++ errno = display->last_error;
++ ret = -1;
++ } else {
++ /* We don't make EPIPE a fatal error here, so that we may try to
++ * read events after the failed flush. When the compositor sends
++ * an error it will close the socket, and if we make EPIPE fatal
++ * here we don't get a chance to process the error. */
++ ret = wl_connection_flush(display->connection);
++ if (ret < 0 && errno != EAGAIN && errno != EPIPE)
++ display_fatal_error(display, errno);
++ }
++
++ pthread_mutex_unlock(&display->mutex);
++
++ return ret;
++}
++
++/** Set the user data associated with a proxy
++ *
++ * \param proxy The proxy object
++ * \param user_data The data to be associated with proxy
++ *
++ * Set the user data associated with \c proxy. When events for this
++ * proxy are received, \c user_data will be supplied to its listener.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void
++wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data)
++{
++ proxy->user_data = user_data;
++}
++
++/** Get the user data associated with a proxy
++ *
++ * \param proxy The proxy object
++ * \return The user data associated with proxy
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void *
++wl_proxy_get_user_data(struct wl_proxy *proxy)
++{
++ return proxy->user_data;
++}
++
++/** Get the protocol object version of a proxy object
++ *
++ * \param proxy The proxy object
++ * \return The protocol object version of the proxy or 0
++ *
++ * Gets the protocol object version of a proxy object, or 0
++ * if the proxy was created with unversioned API.
++ *
++ * A returned value of 0 means that no version information is
++ * available, so the caller must make safe assumptions about
++ * the object's real version.
++ *
++ * wl_display's version will always return 0.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT uint32_t
++wl_proxy_get_version(struct wl_proxy *proxy)
++{
++ return proxy->version;
++}
++
++/** Get the id of a proxy object
++ *
++ * \param proxy The proxy object
++ * \return The id the object associated with the proxy
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT uint32_t
++wl_proxy_get_id(struct wl_proxy *proxy)
++{
++ return proxy->object.id;
++}
++
++/** Set the tag of a proxy object
++ *
++ * A toolkit or application can set a unique tag on a proxy in order to
++ * identify whether an object is managed by itself or some external part.
++ *
++ * To create a tag, the recommended way is to define a statically allocated
++ * constant char array containing some descriptive string. The tag will be the
++ * pointer to the non-const pointer to the beginning of the array.
++ *
++ * For example, to define and set a tag on a surface managed by a certain
++ * subsystem:
++ *
++ * static const char *my_tag = "my tag";
++ *
++ * wl_proxy_set_tag((struct wl_proxy *) surface, &my_tag);
++ *
++ * Then, in a callback with wl_surface as an argument, in order to check
++ * whether it's a surface managed by the same subsystem.
++ *
++ * const char * const *tag;
++ *
++ * tag = wl_proxy_get_tag((struct wl_proxy *) surface);
++ * if (tag != &my_tag)
++ * return;
++ *
++ * ...
++ *
++ * For debugging purposes, a tag should be suitable to be included in a debug
++ * log entry, e.g.
++ *
++ * const char * const *tag;
++ *
++ * tag = wl_proxy_get_tag((struct wl_proxy *) surface);
++ * printf("Got a surface with the tag %p (%s)\n",
++ * tag, (tag && *tag) ? *tag : "");
++ *
++ * \param proxy The proxy object
++ * \param tag The tag
++ *
++ * \memberof wl_proxy
++ * \since 1.17.90
++ */
++WL_EXPORT void
++wl_proxy_set_tag(struct wl_proxy *proxy,
++ const char * const *tag)
++{
++ proxy->tag = tag;
++}
++
++/** Get the tag of a proxy object
++ *
++ * See wl_proxy_set_tag for details.
++ *
++ * \param proxy The proxy object
++ *
++ * \memberof wl_proxy
++ * \since 1.17.90
++ */
++WL_EXPORT const char * const *
++wl_proxy_get_tag(struct wl_proxy *proxy)
++{
++ return proxy->tag;
++}
++
++/** Get the interface name (class) of a proxy object
++ *
++ * \param proxy The proxy object
++ * \return The interface name of the object associated with the proxy
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT const char *
++wl_proxy_get_class(struct wl_proxy *proxy)
++{
++ return proxy->object.interface->name;
++}
++
++/** Assign a proxy to an event queue
++ *
++ * \param proxy The proxy object
++ * \param queue The event queue that will handle this proxy or NULL
++ *
++ * Assign proxy to event queue. Events coming from \c proxy will be
++ * queued in \c queue from now. If queue is NULL, then the display's
++ * default queue is set to the proxy.
++ *
++ * In order to guarantee proper handing of all events which were queued
++ * before the queue change takes effect, it is required to dispatch the
++ * proxy's old event queue after setting a new event queue.
++ *
++ * This is particularly important for multi-threaded setups, where it is
++ * possible for events to be queued to the proxy's old queue from a
++ * different thread during the invocation of this function.
++ *
++ * To ensure that all events for a newly created proxy are dispatched
++ * on a particular queue, it is necessary to use a proxy wrapper if
++ * events are read and dispatched on more than one thread. See
++ * wl_proxy_create_wrapper() for more details.
++ *
++ * \note By default, the queue set in proxy is the one inherited from parent.
++ *
++ * \sa wl_display_dispatch_queue()
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void
++wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue)
++{
++ pthread_mutex_lock(&proxy->display->mutex);
++
++ if (queue) {
++ assert(proxy->display == queue->display);
++ proxy->queue = queue;
++ } else {
++ proxy->queue = &proxy->display->default_queue;
++ }
++
++ pthread_mutex_unlock(&proxy->display->mutex);
++}
++
++/** Create a proxy wrapper for making queue assignments thread-safe
++ *
++ * \param proxy The proxy object to be wrapped
++ * \return A proxy wrapper for the given proxy or NULL on failure
++ *
++ * A proxy wrapper is type of 'struct wl_proxy' instance that can be used when
++ * sending requests instead of using the original proxy. A proxy wrapper does
++ * not have an implementation or dispatcher, and events received on the
++ * object is still emitted on the original proxy. Trying to set an
++ * implementation or dispatcher will have no effect but result in a warning
++ * being logged.
++ *
++ * Setting the proxy queue of the proxy wrapper will make new objects created
++ * using the proxy wrapper use the set proxy queue.
++ * Even though there is no implementation nor dispatcher, the proxy queue can
++ * be changed. This will affect the default queue of new objects created by
++ * requests sent via the proxy wrapper.
++ *
++ * A proxy wrapper can only be destroyed using wl_proxy_wrapper_destroy().
++ *
++ * A proxy wrapper must be destroyed before the proxy it was created from.
++ *
++ * If a user reads and dispatches events on more than one thread, it is
++ * necessary to use a proxy wrapper when sending requests on objects when the
++ * intention is that a newly created proxy is to use a proxy queue different
++ * from the proxy the request was sent on, as creating the new proxy and then
++ * setting the queue is not thread safe.
++ *
++ * For example, a module that runs using its own proxy queue that needs to
++ * do display roundtrip must wrap the wl_display proxy object before sending
++ * the wl_display.sync request. For example:
++ *
++ * \code
++ *
++ * struct wl_event_queue *queue = ...;
++ * struct wl_display *wrapped_display;
++ * struct wl_callback *callback;
++ *
++ * wrapped_display = wl_proxy_create_wrapper(display);
++ * wl_proxy_set_queue((struct wl_proxy *) wrapped_display, queue);
++ * callback = wl_display_sync(wrapped_display);
++ * wl_proxy_wrapper_destroy(wrapped_display);
++ * wl_callback_add_listener(callback, ...);
++ *
++ * \endcode
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void *
++wl_proxy_create_wrapper(void *proxy)
++{
++ struct wl_proxy *wrapped_proxy = proxy;
++ struct wl_proxy *wrapper;
++
++ wrapper = zalloc(sizeof *wrapper);
++ if (!wrapper)
++ return NULL;
++
++ pthread_mutex_lock(&wrapped_proxy->display->mutex);
++
++ wrapper->object.interface = wrapped_proxy->object.interface;
++ wrapper->object.id = wrapped_proxy->object.id;
++ wrapper->version = wrapped_proxy->version;
++ wrapper->display = wrapped_proxy->display;
++ wrapper->queue = wrapped_proxy->queue;
++ wrapper->flags = WL_PROXY_FLAG_WRAPPER;
++ wrapper->refcount = 1;
++
++ pthread_mutex_unlock(&wrapped_proxy->display->mutex);
++
++ return wrapper;
++}
++
++/** Destroy a proxy wrapper
++ * \param proxy_wrapper The proxy wrapper to be destroyed
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void
++wl_proxy_wrapper_destroy(void *proxy_wrapper)
++{
++ struct wl_proxy *wrapper = proxy_wrapper;
++
++ if (!(wrapper->flags & WL_PROXY_FLAG_WRAPPER))
++ wl_abort("Tried to destroy non-wrapper proxy with "
++ "wl_proxy_wrapper_destroy\n");
++
++ assert(wrapper->refcount == 1);
++
++ free(wrapper);
++}
++
++WL_EXPORT void
++wl_log_set_handler_client(wl_log_func_t handler)
++{
++ wl_log_handler = handler;
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++/** \file
++ *
++ * \brief Include the client API and protocol C API.
++ *
++ * \warning Use of this header file is discouraged. Prefer including
++ * wayland-client-core.h instead, which does not include the
++ * client protocol header and as such only defines the library
++ * API.
++ */
++
++#ifndef WAYLAND_CLIENT_H
++#define WAYLAND_CLIENT_H
++
++#include "wayland-client-core.h"
++#include "wayland-client-protocol.h"
++
++#endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++
++#include "../config.h"
++
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <string.h>
++#include <sys/epoll.h>
++#include <sys/mman.h>
++#include <sys/un.h>
++#ifdef HAVE_SYS_UCRED_H
++#include <sys/ucred.h>
++#endif
++
++#include "wayland-os.h"
++
++static int
++set_cloexec_or_close(int fd)
++{
++ long flags;
++
++ if (fd == -1)
++ return -1;
++
++ flags = fcntl(fd, F_GETFD);
++ if (flags == -1)
++ goto err;
++
++ if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
++ goto err;
++
++ return fd;
++
++err:
++ close(fd);
++ return -1;
++}
++
++int
++wl_os_socket_cloexec(int domain, int type, int protocol)
++{
++ int fd;
++
++ fd = socket(domain, type | SOCK_CLOEXEC, protocol);
++ if (fd >= 0)
++ return fd;
++ if (errno != EINVAL)
++ return -1;
++
++ fd = socket(domain, type, protocol);
++ return set_cloexec_or_close(fd);
++}
++
++#if defined(__FreeBSD__)
++int
++wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid)
++{
++ socklen_t len;
++ struct xucred ucred;
++
++ len = sizeof(ucred);
++ if (getsockopt(sockfd, SOL_LOCAL, LOCAL_PEERCRED, &ucred, &len) < 0 ||
++ ucred.cr_version != XUCRED_VERSION)
++ return -1;
++ *uid = ucred.cr_uid;
++ *gid = ucred.cr_gid;
++#if HAVE_XUCRED_CR_PID
++ /* Since https://cgit.freebsd.org/src/commit/?id=c5afec6e895a */
++ *pid = ucred.cr_pid;
++#else
++ *pid = 0;
++#endif
++ return 0;
++}
++#elif defined(SO_PEERCRED)
++int
++wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid)
++{
++ socklen_t len;
++ struct ucred ucred;
++
++ len = sizeof(ucred);
++ if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0)
++ return -1;
++ *uid = ucred.uid;
++ *gid = ucred.gid;
++ *pid = ucred.pid;
++ return 0;
++}
++#else
++#error "Don't know how to read ucred on this platform"
++#endif
++
++int
++wl_os_dupfd_cloexec(int fd, int minfd)
++{
++ int newfd;
++
++ newfd = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
++ if (newfd >= 0)
++ return newfd;
++ if (errno != EINVAL)
++ return -1;
++
++ newfd = fcntl(fd, F_DUPFD, minfd);
++ return set_cloexec_or_close(newfd);
++}
++
++static ssize_t
++recvmsg_cloexec_fallback(int sockfd, struct msghdr *msg, int flags)
++{
++ ssize_t len;
++ struct cmsghdr *cmsg;
++ unsigned char *data;
++ int *fd;
++ int *end;
++
++ len = recvmsg(sockfd, msg, flags);
++ if (len == -1)
++ return -1;
++
++ if (!msg->msg_control || msg->msg_controllen == 0)
++ return len;
++
++ cmsg = CMSG_FIRSTHDR(msg);
++ for (; cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) {
++ if (cmsg->cmsg_level != SOL_SOCKET ||
++ cmsg->cmsg_type != SCM_RIGHTS)
++ continue;
++
++ data = CMSG_DATA(cmsg);
++ end = (int *)(data + cmsg->cmsg_len - CMSG_LEN(0));
++ for (fd = (int *)data; fd < end; ++fd)
++ *fd = set_cloexec_or_close(*fd);
++ }
++
++ return len;
++}
++
++ssize_t
++wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags)
++{
++#if HAVE_BROKEN_MSG_CMSG_CLOEXEC
++ /*
++ * FreeBSD had a broken implementation of MSG_CMSG_CLOEXEC between 2015
++ * and 2021, so we have to use the non-MSG_CMSG_CLOEXEC fallback
++ * directly when compiling against a version that does not include the
++ * fix (https://cgit.freebsd.org/src/commit/?id=6ceacebdf52211).
++ */
++#pragma message("Using fallback directly since MSG_CMSG_CLOEXEC is broken.")
++#else
++ ssize_t len;
++
++ len = recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC);
++ if (len >= 0)
++ return len;
++ if (errno != EINVAL)
++ return -1;
++#endif
++ return recvmsg_cloexec_fallback(sockfd, msg, flags);
++}
++
++int
++wl_os_epoll_create_cloexec(void)
++{
++ int fd;
++
++#ifdef EPOLL_CLOEXEC
++ fd = epoll_create1(EPOLL_CLOEXEC);
++ if (fd >= 0)
++ return fd;
++ if (errno != EINVAL)
++ return -1;
++#endif
++
++ fd = epoll_create(1);
++ return set_cloexec_or_close(fd);
++}
++
++int
++wl_os_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
++{
++ int fd;
++
++#ifdef HAVE_ACCEPT4
++ fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC);
++ if (fd >= 0)
++ return fd;
++ if (errno != ENOSYS)
++ return -1;
++#endif
++
++ fd = accept(sockfd, addr, addrlen);
++ return set_cloexec_or_close(fd);
++}
++
++/*
++ * Fallback function for operating systems that don't implement
++ * mremap(MREMAP_MAYMOVE).
++ */
++void *
++wl_os_mremap_maymove(int fd, void *old_data, ssize_t *old_size,
++ ssize_t new_size, int prot, int flags)
++{
++ void *result;
++
++ /* Make sure any pending write is flushed. */
++ if (msync(old_data, *old_size, MS_SYNC) != 0)
++ return MAP_FAILED;
++
++ /* We could try mapping a new block immediately after the current one
++ * with MAP_FIXED, however that is not guaranteed to work and breaks
++ * on CHERI-enabled architectures since the data pointer will still
++ * have the bounds of the previous allocation.
++ */
++ result = mmap(NULL, new_size, prot, flags, fd, 0);
++ if (result == MAP_FAILED)
++ return MAP_FAILED;
++
++ if (munmap(old_data, *old_size) == 0)
++ *old_size = 0;
++
++ return result;
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_OS_H
++#define WAYLAND_OS_H
++
++#include <sys/types.h>
++#include <sys/socket.h>
++
++int
++wl_os_socket_cloexec(int domain, int type, int protocol);
++
++int
++wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid);
++
++int
++wl_os_dupfd_cloexec(int fd, int minfd);
++
++ssize_t
++wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags);
++
++int
++wl_os_epoll_create_cloexec(void);
++
++int
++wl_os_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
++
++void *
++wl_os_mremap_maymove(int fd, void *old_data, ssize_t *old_size,
++ ssize_t new_size, int prot, int flags);
++
++
++/*
++ * The following are for wayland-os.c and the unit tests.
++ * Do not use them elsewhere.
++ */
++
++#ifdef __linux__
++
++#ifndef SOCK_CLOEXEC
++#define SOCK_CLOEXEC 02000000
++#endif
++
++#ifndef F_DUPFD_CLOEXEC
++#define F_DUPFD_CLOEXEC 1030
++#endif
++
++#ifndef MSG_CMSG_CLOEXEC
++#define MSG_CMSG_CLOEXEC 0x40000000
++#endif
++
++#endif /* __linux__ */
++
++#endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2011 Intel Corporation
++ * Copyright © 2013 Jason Ekstrand
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_PRIVATE_H
++#define WAYLAND_PRIVATE_H
++
++#include <stdarg.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <stdbool.h>
++
++#define WL_HIDE_DEPRECATED 1
++
++#include "wayland-util.h"
++
++/* Invalid memory address */
++#define WL_ARRAY_POISON_PTR (void *) 4
++
++#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
++
++#define WL_MAP_SERVER_SIDE 0
++#define WL_MAP_CLIENT_SIDE 1
++#define WL_SERVER_ID_START 0xff000000
++#define WL_MAP_MAX_OBJECTS 0x00f00000
++#define WL_CLOSURE_MAX_ARGS 20
++
++struct wl_object {
++ const struct wl_interface *interface;
++ const void *implementation;
++ uint32_t id;
++};
++
++int
++wl_interface_equal(const struct wl_interface *iface1,
++ const struct wl_interface *iface2);
++
++/* Flags for wl_map_insert_new and wl_map_insert_at. Flags can be queried with
++ * wl_map_lookup_flags. The current implementation has room for 1 bit worth of
++ * flags. If more flags are ever added, the implementation of wl_map will have
++ * to change to allow for new flags */
++enum wl_map_entry_flags {
++ WL_MAP_ENTRY_LEGACY = (1 << 0), /* Server side only */
++ WL_MAP_ENTRY_ZOMBIE = (1 << 0) /* Client side only */
++};
++
++struct wl_map {
++ struct wl_array client_entries;
++ struct wl_array server_entries;
++ uint32_t side;
++ uint32_t free_list;
++};
++
++typedef enum wl_iterator_result (*wl_iterator_func_t)(void *element,
++ void *data,
++ uint32_t flags);
++
++void
++wl_map_init(struct wl_map *map, uint32_t side);
++
++void
++wl_map_release(struct wl_map *map);
++
++uint32_t
++wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data);
++
++int
++wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void *data);
++
++int
++wl_map_reserve_new(struct wl_map *map, uint32_t i);
++
++void
++wl_map_remove(struct wl_map *map, uint32_t i);
++
++void *
++wl_map_lookup(struct wl_map *map, uint32_t i);
++
++uint32_t
++wl_map_lookup_flags(struct wl_map *map, uint32_t i);
++
++void
++wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data);
++
++struct wl_connection *
++wl_connection_create(int fd);
++
++int
++wl_connection_destroy(struct wl_connection *connection);
++
++void
++wl_connection_copy(struct wl_connection *connection, void *data, size_t size);
++
++void
++wl_connection_consume(struct wl_connection *connection, size_t size);
++
++int
++wl_connection_flush(struct wl_connection *connection);
++
++uint32_t
++wl_connection_pending_input(struct wl_connection *connection);
++
++int
++wl_connection_read(struct wl_connection *connection);
++
++int
++wl_connection_write(struct wl_connection *connection,
++ const void *data, size_t count);
++
++int
++wl_connection_queue(struct wl_connection *connection,
++ const void *data, size_t count);
++
++int
++wl_connection_get_fd(struct wl_connection *connection);
++
++struct wl_closure {
++ int count;
++ const struct wl_message *message;
++ uint32_t opcode;
++ uint32_t sender_id;
++ union wl_argument args[WL_CLOSURE_MAX_ARGS];
++ struct wl_list link;
++ struct wl_proxy *proxy;
++ struct wl_array extra[0];
++};
++
++struct argument_details {
++ char type;
++ int nullable;
++};
++
++const char *
++get_next_argument(const char *signature, struct argument_details *details);
++
++int
++arg_count_for_signature(const char *signature);
++
++int
++wl_message_count_arrays(const struct wl_message *message);
++
++int
++wl_message_get_since(const struct wl_message *message);
++
++void
++wl_argument_from_va_list(const char *signature, union wl_argument *args,
++ int count, va_list ap);
++
++struct wl_closure *
++wl_closure_marshal(struct wl_object *sender,
++ uint32_t opcode, union wl_argument *args,
++ const struct wl_message *message);
++
++struct wl_closure *
++wl_closure_vmarshal(struct wl_object *sender,
++ uint32_t opcode, va_list ap,
++ const struct wl_message *message);
++
++struct wl_closure *
++wl_connection_demarshal(struct wl_connection *connection,
++ uint32_t size,
++ struct wl_map *objects,
++ const struct wl_message *message);
++
++bool
++wl_object_is_zombie(struct wl_map *map, uint32_t id);
++
++int
++wl_closure_lookup_objects(struct wl_closure *closure, struct wl_map *objects);
++
++enum wl_closure_invoke_flag {
++ WL_CLOSURE_INVOKE_CLIENT = (1 << 0),
++ WL_CLOSURE_INVOKE_SERVER = (1 << 1)
++};
++
++void
++wl_closure_invoke(struct wl_closure *closure, uint32_t flags,
++ struct wl_object *target, uint32_t opcode, void *data);
++
++void
++wl_closure_dispatch(struct wl_closure *closure, wl_dispatcher_func_t dispatcher,
++ struct wl_object *target, uint32_t opcode);
++
++int
++wl_closure_send(struct wl_closure *closure, struct wl_connection *connection);
++
++int
++wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection);
++
++void
++wl_closure_print(struct wl_closure *closure,
++ struct wl_object *target, int send, int discarded,
++ uint32_t (*n_parse)(union wl_argument *arg));
++
++void
++wl_closure_destroy(struct wl_closure *closure);
++
++extern wl_log_func_t wl_log_handler;
++
++void wl_log(const char *fmt, ...);
++void wl_abort(const char *fmt, ...);
++
++struct wl_display;
++
++struct wl_array *
++wl_display_get_additional_shm_formats(struct wl_display *display);
++
++static inline void *
++zalloc(size_t s)
++{
++ return calloc(1, s);
++}
++
++void
++wl_connection_close_fds_in(struct wl_connection *connection, int max);
++
++#endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_SERVER_CORE_H
++#define WAYLAND_SERVER_CORE_H
++
++#include <sys/types.h>
++#include <stdint.h>
++#include <stdbool.h>
++#include "wayland-util.h"
++#include "wayland-version.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++enum {
++ WL_EVENT_READABLE = 0x01,
++ WL_EVENT_WRITABLE = 0x02,
++ WL_EVENT_HANGUP = 0x04,
++ WL_EVENT_ERROR = 0x08
++};
++
++/** File descriptor dispatch function type
++ *
++ * Functions of this type are used as callbacks for file descriptor events.
++ *
++ * \param fd The file descriptor delivering the event.
++ * \param mask Describes the kind of the event as a bitwise-or of:
++ * \c WL_EVENT_READABLE, \c WL_EVENT_WRITABLE, \c WL_EVENT_HANGUP,
++ * \c WL_EVENT_ERROR.
++ * \param data The user data argument of the related wl_event_loop_add_fd()
++ * call.
++ * \return If the event source is registered for re-check with
++ * wl_event_source_check(): 0 for all done, 1 for needing a re-check.
++ * If not registered, the return value is ignored and should be zero.
++ *
++ * \sa wl_event_loop_add_fd()
++ * \memberof wl_event_source
++ */
++typedef int (*wl_event_loop_fd_func_t)(int fd, uint32_t mask, void *data);
++
++/** Timer dispatch function type
++ *
++ * Functions of this type are used as callbacks for timer expiry.
++ *
++ * \param data The user data argument of the related wl_event_loop_add_timer()
++ * call.
++ * \return If the event source is registered for re-check with
++ * wl_event_source_check(): 0 for all done, 1 for needing a re-check.
++ * If not registered, the return value is ignored and should be zero.
++ *
++ * \sa wl_event_loop_add_timer()
++ * \memberof wl_event_source
++ */
++typedef int (*wl_event_loop_timer_func_t)(void *data);
++
++/** Signal dispatch function type
++ *
++ * Functions of this type are used as callbacks for (POSIX) signals.
++ *
++ * \param signal_number
++ * \param data The user data argument of the related wl_event_loop_add_signal()
++ * call.
++ * \return If the event source is registered for re-check with
++ * wl_event_source_check(): 0 for all done, 1 for needing a re-check.
++ * If not registered, the return value is ignored and should be zero.
++ *
++ * \sa wl_event_loop_add_signal()
++ * \memberof wl_event_source
++ */
++typedef int (*wl_event_loop_signal_func_t)(int signal_number, void *data);
++
++/** Idle task function type
++ *
++ * Functions of this type are used as callbacks before blocking in
++ * wl_event_loop_dispatch().
++ *
++ * \param data The user data argument of the related wl_event_loop_add_idle()
++ * call.
++ *
++ * \sa wl_event_loop_add_idle() wl_event_loop_dispatch()
++ * \memberof wl_event_source
++ */
++typedef void (*wl_event_loop_idle_func_t)(void *data);
++
++/** \struct wl_event_loop
++ *
++ * \brief An event loop context
++ *
++ * Usually you create an event loop context, add sources to it, and call
++ * wl_event_loop_dispatch() in a loop to process events.
++ *
++ * \sa wl_event_source
++ */
++
++/** \struct wl_event_source
++ *
++ * \brief An abstract event source
++ *
++ * This is the generic type for fd, timer, signal, and idle sources.
++ * Functions that operate on specific source types must not be used with
++ * a different type, even if the function signature allows it.
++ */
++
++struct wl_event_loop *
++wl_event_loop_create(void);
++
++void
++wl_event_loop_destroy(struct wl_event_loop *loop);
++
++struct wl_event_source *
++wl_event_loop_add_fd(struct wl_event_loop *loop,
++ int fd, uint32_t mask,
++ wl_event_loop_fd_func_t func,
++ void *data);
++
++int
++wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask);
++
++struct wl_event_source *
++wl_event_loop_add_timer(struct wl_event_loop *loop,
++ wl_event_loop_timer_func_t func,
++ void *data);
++
++struct wl_event_source *
++wl_event_loop_add_signal(struct wl_event_loop *loop,
++ int signal_number,
++ wl_event_loop_signal_func_t func,
++ void *data);
++
++int
++wl_event_source_timer_update(struct wl_event_source *source,
++ int ms_delay);
++
++int
++wl_event_source_remove(struct wl_event_source *source);
++
++void
++wl_event_source_check(struct wl_event_source *source);
++
++int
++wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout);
++
++void
++wl_event_loop_dispatch_idle(struct wl_event_loop *loop);
++
++struct wl_event_source *
++wl_event_loop_add_idle(struct wl_event_loop *loop,
++ wl_event_loop_idle_func_t func,
++ void *data);
++
++int
++wl_event_loop_get_fd(struct wl_event_loop *loop);
++
++struct wl_listener;
++
++typedef void (*wl_notify_func_t)(struct wl_listener *listener, void *data);
++
++void
++wl_event_loop_add_destroy_listener(struct wl_event_loop *loop,
++ struct wl_listener *listener);
++
++struct wl_listener *
++wl_event_loop_get_destroy_listener(struct wl_event_loop *loop,
++ wl_notify_func_t notify);
++
++struct wl_display *
++wl_display_create(void);
++
++void
++wl_display_destroy(struct wl_display *display);
++
++struct wl_event_loop *
++wl_display_get_event_loop(struct wl_display *display);
++
++int
++wl_display_add_socket(struct wl_display *display, const char *name);
++
++const char *
++wl_display_add_socket_auto(struct wl_display *display);
++
++int
++wl_display_add_socket_fd(struct wl_display *display, int sock_fd);
++
++void
++wl_display_terminate(struct wl_display *display);
++
++void
++wl_display_run(struct wl_display *display);
++
++void
++wl_display_flush_clients(struct wl_display *display);
++
++void
++wl_display_destroy_clients(struct wl_display *display);
++
++struct wl_client;
++
++typedef void (*wl_global_bind_func_t)(struct wl_client *client, void *data,
++ uint32_t version, uint32_t id);
++
++uint32_t
++wl_display_get_serial(struct wl_display *display);
++
++uint32_t
++wl_display_next_serial(struct wl_display *display);
++
++void
++wl_display_add_destroy_listener(struct wl_display *display,
++ struct wl_listener *listener);
++
++void
++wl_display_add_client_created_listener(struct wl_display *display,
++ struct wl_listener *listener);
++
++struct wl_listener *
++wl_display_get_destroy_listener(struct wl_display *display,
++ wl_notify_func_t notify);
++
++struct wl_global *
++wl_global_create(struct wl_display *display,
++ const struct wl_interface *interface,
++ int version,
++ void *data, wl_global_bind_func_t bind);
++
++void
++wl_global_remove(struct wl_global *global);
++
++void
++wl_global_destroy(struct wl_global *global);
++
++/** A filter function for wl_global objects
++ *
++ * \param client The client object
++ * \param global The global object to show or hide
++ * \param data The user data pointer
++ *
++ * A filter function enables the server to decide which globals to
++ * advertise to each client.
++ *
++ * When a wl_global filter is set, the given callback function will be
++ * called during wl_global advertisement and binding.
++ *
++ * This function should return true if the global object should be made
++ * visible to the client or false otherwise.
++ */
++typedef bool (*wl_display_global_filter_func_t)(const struct wl_client *client,
++ const struct wl_global *global,
++ void *data);
++
++void
++wl_display_set_global_filter(struct wl_display *display,
++ wl_display_global_filter_func_t filter,
++ void *data);
++
++const struct wl_interface *
++wl_global_get_interface(const struct wl_global *global);
++
++uint32_t
++wl_global_get_version(const struct wl_global *global);
++
++struct wl_display *
++wl_global_get_display(const struct wl_global *global);
++
++void *
++wl_global_get_user_data(const struct wl_global *global);
++
++void
++wl_global_set_user_data(struct wl_global *global, void *data);
++
++struct wl_client *
++wl_client_create(struct wl_display *display, int fd);
++
++struct wl_list *
++wl_display_get_client_list(struct wl_display *display);
++
++struct wl_list *
++wl_client_get_link(struct wl_client *client);
++
++struct wl_client *
++wl_client_from_link(struct wl_list *link);
++
++/** Iterate over a list of clients. */
++#define wl_client_for_each(client, list) \
++ for (client = wl_client_from_link((list)->next); \
++ wl_client_get_link(client) != (list); \
++ client = wl_client_from_link(wl_client_get_link(client)->next))
++
++void
++wl_client_destroy(struct wl_client *client);
++
++void
++wl_client_flush(struct wl_client *client);
++
++void
++wl_client_get_credentials(struct wl_client *client,
++ pid_t *pid, uid_t *uid, gid_t *gid);
++
++int
++wl_client_get_fd(struct wl_client *client);
++
++void
++wl_client_add_destroy_listener(struct wl_client *client,
++ struct wl_listener *listener);
++
++struct wl_listener *
++wl_client_get_destroy_listener(struct wl_client *client,
++ wl_notify_func_t notify);
++
++struct wl_resource *
++wl_client_get_object(struct wl_client *client, uint32_t id);
++
++void
++wl_client_post_no_memory(struct wl_client *client);
++
++void
++wl_client_post_implementation_error(struct wl_client *client,
++ const char* msg, ...) WL_PRINTF(2,3);
++
++void
++wl_client_add_resource_created_listener(struct wl_client *client,
++ struct wl_listener *listener);
++
++typedef enum wl_iterator_result (*wl_client_for_each_resource_iterator_func_t)(
++ struct wl_resource *resource,
++ void *user_data);
++
++void
++wl_client_for_each_resource(struct wl_client *client,
++ wl_client_for_each_resource_iterator_func_t iterator,
++ void *user_data);
++
++/** \class wl_listener
++ *
++ * \brief A single listener for Wayland signals
++ *
++ * wl_listener provides the means to listen for wl_signal notifications. Many
++ * Wayland objects use wl_listener for notification of significant events like
++ * object destruction.
++ *
++ * Clients should create wl_listener objects manually and can register them as
++ * listeners to signals using #wl_signal_add, assuming the signal is
++ * directly accessible. For opaque structs like wl_event_loop, adding a
++ * listener should be done through provided accessor methods. A listener can
++ * only listen to one signal at a time.
++ *
++ * \code
++ * struct wl_listener your_listener;
++ *
++ * your_listener.notify = your_callback_method;
++ *
++ * // Direct access
++ * wl_signal_add(&some_object->destroy_signal, &your_listener);
++ *
++ * // Accessor access
++ * wl_event_loop *loop = ...;
++ * wl_event_loop_add_destroy_listener(loop, &your_listener);
++ * \endcode
++ *
++ * If the listener is part of a larger struct, #wl_container_of can be used
++ * to retrieve a pointer to it:
++ *
++ * \code
++ * void your_listener(struct wl_listener *listener, void *data)
++ * {
++ * struct your_data *data;
++ *
++ * your_data = wl_container_of(listener, data, your_member_name);
++ * }
++ * \endcode
++ *
++ * If you need to remove a listener from a signal, use wl_list_remove().
++ *
++ * \code
++ * wl_list_remove(&your_listener.link);
++ * \endcode
++ *
++ * \sa wl_signal
++ */
++struct wl_listener {
++ struct wl_list link;
++ wl_notify_func_t notify;
++};
++
++/** \class wl_signal
++ *
++ * \brief A source of a type of observable event
++ *
++ * Signals are recognized points where significant events can be observed.
++ * Compositors as well as the server can provide signals. Observers are
++ * wl_listener's that are added through #wl_signal_add. Signals are emitted
++ * using #wl_signal_emit, which will invoke all listeners until that
++ * listener is removed by wl_list_remove() (or whenever the signal is
++ * destroyed).
++ *
++ * \sa wl_listener for more information on using wl_signal
++ */
++struct wl_signal {
++ struct wl_list listener_list;
++};
++
++/** Initialize a new \ref wl_signal for use.
++ *
++ * \param signal The signal that will be initialized
++ *
++ * \memberof wl_signal
++ */
++static inline void
++wl_signal_init(struct wl_signal *signal)
++{
++ wl_list_init(&signal->listener_list);
++}
++
++/** Add the specified listener to this signal.
++ *
++ * \param signal The signal that will emit events to the listener
++ * \param listener The listener to add
++ *
++ * \memberof wl_signal
++ */
++static inline void
++wl_signal_add(struct wl_signal *signal, struct wl_listener *listener)
++{
++ wl_list_insert(signal->listener_list.prev, &listener->link);
++}
++
++/** Gets the listener struct for the specified callback.
++ *
++ * \param signal The signal that contains the specified listener
++ * \param notify The listener that is the target of this search
++ * \return the list item that corresponds to the specified listener, or NULL
++ * if none was found
++ *
++ * \memberof wl_signal
++ */
++static inline struct wl_listener *
++wl_signal_get(struct wl_signal *signal, wl_notify_func_t notify)
++{
++ struct wl_listener *l;
++
++ wl_list_for_each(l, &signal->listener_list, link)
++ if (l->notify == notify)
++ return l;
++
++ return NULL;
++}
++
++/** Emits this signal, notifying all registered listeners.
++ *
++ * \param signal The signal object that will emit the signal
++ * \param data The data that will be emitted with the signal
++ *
++ * \memberof wl_signal
++ */
++static inline void
++wl_signal_emit(struct wl_signal *signal, void *data)
++{
++ struct wl_listener *l, *next;
++
++ wl_list_for_each_safe(l, next, &signal->listener_list, link)
++ l->notify(l, data);
++}
++
++void
++wl_signal_emit_mutable(struct wl_signal *signal, void *data);
++
++typedef void (*wl_resource_destroy_func_t)(struct wl_resource *resource);
++
++/*
++ * Post an event to the client's object referred to by 'resource'.
++ * 'opcode' is the event number generated from the protocol XML
++ * description (the event name). The variable arguments are the event
++ * parameters, in the order they appear in the protocol XML specification.
++ *
++ * The variable arguments' types are:
++ * - type=uint: uint32_t
++ * - type=int: int32_t
++ * - type=fixed: wl_fixed_t
++ * - type=string: (const char *) to a nil-terminated string
++ * - type=array: (struct wl_array *)
++ * - type=fd: int, that is an open file descriptor
++ * - type=new_id: (struct wl_object *) or (struct wl_resource *)
++ * - type=object: (struct wl_object *) or (struct wl_resource *)
++ */
++void
++wl_resource_post_event(struct wl_resource *resource,
++ uint32_t opcode, ...);
++
++void
++wl_resource_post_event_array(struct wl_resource *resource,
++ uint32_t opcode, union wl_argument *args);
++
++void
++wl_resource_queue_event(struct wl_resource *resource,
++ uint32_t opcode, ...);
++
++void
++wl_resource_queue_event_array(struct wl_resource *resource,
++ uint32_t opcode, union wl_argument *args);
++
++/* msg is a printf format string, variable args are its args. */
++void
++wl_resource_post_error(struct wl_resource *resource,
++ uint32_t code, const char *msg, ...) WL_PRINTF(3, 4);
++
++void
++wl_resource_post_no_memory(struct wl_resource *resource);
++
++struct wl_display *
++wl_client_get_display(struct wl_client *client);
++
++struct wl_resource *
++wl_resource_create(struct wl_client *client,
++ const struct wl_interface *interface,
++ int version, uint32_t id);
++
++void
++wl_resource_set_implementation(struct wl_resource *resource,
++ const void *implementation,
++ void *data,
++ wl_resource_destroy_func_t destroy);
++
++void
++wl_resource_set_dispatcher(struct wl_resource *resource,
++ wl_dispatcher_func_t dispatcher,
++ const void *implementation,
++ void *data,
++ wl_resource_destroy_func_t destroy);
++
++void
++wl_resource_destroy(struct wl_resource *resource);
++
++uint32_t
++wl_resource_get_id(struct wl_resource *resource);
++
++struct wl_list *
++wl_resource_get_link(struct wl_resource *resource);
++
++struct wl_resource *
++wl_resource_from_link(struct wl_list *resource);
++
++struct wl_resource *
++wl_resource_find_for_client(struct wl_list *list, struct wl_client *client);
++
++struct wl_client *
++wl_resource_get_client(struct wl_resource *resource);
++
++void
++wl_resource_set_user_data(struct wl_resource *resource, void *data);
++
++void *
++wl_resource_get_user_data(struct wl_resource *resource);
++
++int
++wl_resource_get_version(struct wl_resource *resource);
++
++void
++wl_resource_set_destructor(struct wl_resource *resource,
++ wl_resource_destroy_func_t destroy);
++
++int
++wl_resource_instance_of(struct wl_resource *resource,
++ const struct wl_interface *interface,
++ const void *implementation);
++const char *
++wl_resource_get_class(struct wl_resource *resource);
++
++void
++wl_resource_add_destroy_listener(struct wl_resource *resource,
++ struct wl_listener *listener);
++
++struct wl_listener *
++wl_resource_get_destroy_listener(struct wl_resource *resource,
++ wl_notify_func_t notify);
++
++#define wl_resource_for_each(resource, list) \
++ for (resource = 0, resource = wl_resource_from_link((list)->next); \
++ wl_resource_get_link(resource) != (list); \
++ resource = wl_resource_from_link(wl_resource_get_link(resource)->next))
++
++#define wl_resource_for_each_safe(resource, tmp, list) \
++ for (resource = 0, tmp = 0, \
++ resource = wl_resource_from_link((list)->next), \
++ tmp = wl_resource_from_link((list)->next->next); \
++ wl_resource_get_link(resource) != (list); \
++ resource = tmp, \
++ tmp = wl_resource_from_link(wl_resource_get_link(resource)->next))
++
++struct wl_shm_buffer *
++wl_shm_buffer_get(struct wl_resource *resource);
++
++void
++wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer);
++
++void
++wl_shm_buffer_end_access(struct wl_shm_buffer *buffer);
++
++void *
++wl_shm_buffer_get_data(struct wl_shm_buffer *buffer);
++
++int32_t
++wl_shm_buffer_get_stride(struct wl_shm_buffer *buffer);
++
++uint32_t
++wl_shm_buffer_get_format(struct wl_shm_buffer *buffer);
++
++int32_t
++wl_shm_buffer_get_width(struct wl_shm_buffer *buffer);
++
++int32_t
++wl_shm_buffer_get_height(struct wl_shm_buffer *buffer);
++
++struct wl_shm_pool *
++wl_shm_buffer_ref_pool(struct wl_shm_buffer *buffer);
++
++void
++wl_shm_pool_unref(struct wl_shm_pool *pool);
++
++int
++wl_display_init_shm(struct wl_display *display);
++
++uint32_t *
++wl_display_add_shm_format(struct wl_display *display, uint32_t format);
++
++struct wl_shm_buffer *
++wl_shm_buffer_create(struct wl_client *client,
++ uint32_t id, int32_t width, int32_t height,
++ int32_t stride, uint32_t format) WL_DEPRECATED;
++
++void
++wl_log_set_handler_server(wl_log_func_t handler);
++
++enum wl_protocol_logger_type {
++ WL_PROTOCOL_LOGGER_REQUEST,
++ WL_PROTOCOL_LOGGER_EVENT,
++};
++
++struct wl_protocol_logger_message {
++ struct wl_resource *resource;
++ int message_opcode;
++ const struct wl_message *message;
++ int arguments_count;
++ const union wl_argument *arguments;
++};
++
++typedef void (*wl_protocol_logger_func_t)(void *user_data,
++ enum wl_protocol_logger_type direction,
++ const struct wl_protocol_logger_message *message);
++
++struct wl_protocol_logger *
++wl_display_add_protocol_logger(struct wl_display *display,
++ wl_protocol_logger_func_t, void *user_data);
++
++void
++wl_protocol_logger_destroy(struct wl_protocol_logger *logger);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2011 Intel Corporation
++ * Copyright © 2013 Jason Ekstrand
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_SERVER_PRIVATE_H
++#define WAYLAND_SERVER_PRIVATE_H
++
++#include "wayland-server-core.h"
++
++struct wl_priv_signal {
++ struct wl_list listener_list;
++ struct wl_list emit_list;
++};
++
++void
++wl_priv_signal_init(struct wl_priv_signal *signal);
++
++void
++wl_priv_signal_add(struct wl_priv_signal *signal, struct wl_listener *listener);
++
++struct wl_listener *
++wl_priv_signal_get(struct wl_priv_signal *signal, wl_notify_func_t notify);
++
++void
++wl_priv_signal_emit(struct wl_priv_signal *signal, void *data);
++
++void
++wl_priv_signal_final_emit(struct wl_priv_signal *signal, void *data);
++
++#endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++
++#include <stdbool.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <stddef.h>
++#include <stdio.h>
++#include <stdarg.h>
++#include <errno.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <dlfcn.h>
++#include <assert.h>
++#include <sys/time.h>
++#include <fcntl.h>
++#include <sys/eventfd.h>
++#include <sys/file.h>
++#include <sys/stat.h>
++
++#include "wayland-util.h"
++#include "wayland-private.h"
++#include "wayland-server-private.h"
++#include "wayland-server.h"
++#include "wayland-os.h"
++
++/* This is the size of the char array in struct sock_addr_un.
++ * No Wayland socket can be created with a path longer than this,
++ * including the null terminator.
++ */
++#ifndef UNIX_PATH_MAX
++#define UNIX_PATH_MAX 108
++#endif
++
++#define LOCK_SUFFIX ".lock"
++#define LOCK_SUFFIXLEN 5
++
++struct wl_socket {
++ int fd;
++ int fd_lock;
++ struct sockaddr_un addr;
++ char lock_addr[UNIX_PATH_MAX + LOCK_SUFFIXLEN];
++ struct wl_list link;
++ struct wl_event_source *source;
++ char *display_name;
++};
++
++struct wl_client {
++ struct wl_connection *connection;
++ struct wl_event_source *source;
++ struct wl_display *display;
++ struct wl_resource *display_resource;
++ struct wl_list link;
++ struct wl_map objects;
++ struct wl_priv_signal destroy_signal;
++ pid_t pid;
++ uid_t uid;
++ gid_t gid;
++ int error;
++ struct wl_priv_signal resource_created_signal;
++};
++
++struct wl_display {
++ struct wl_event_loop *loop;
++ int run;
++
++ uint32_t id;
++ uint32_t serial;
++
++ struct wl_list registry_resource_list;
++ struct wl_list global_list;
++ struct wl_list socket_list;
++ struct wl_list client_list;
++ struct wl_list protocol_loggers;
++
++ struct wl_priv_signal destroy_signal;
++ struct wl_priv_signal create_client_signal;
++
++ struct wl_array additional_shm_formats;
++
++ wl_display_global_filter_func_t global_filter;
++ void *global_filter_data;
++
++ int terminate_efd;
++ struct wl_event_source *term_source;
++};
++
++struct wl_global {
++ struct wl_display *display;
++ const struct wl_interface *interface;
++ uint32_t name;
++ uint32_t version;
++ void *data;
++ wl_global_bind_func_t bind;
++ struct wl_list link;
++ bool removed;
++};
++
++struct wl_resource {
++ struct wl_object object;
++ wl_resource_destroy_func_t destroy;
++ struct wl_list link;
++ /* Unfortunately some users of libwayland (e.g. mesa) still use the
++ * deprecated wl_resource struct, even if creating it with the new
++ * wl_resource_create(). So we cannot change the layout of the struct
++ * unless after the data field. */
++ struct wl_signal deprecated_destroy_signal;
++ struct wl_client *client;
++ void *data;
++ int version;
++ wl_dispatcher_func_t dispatcher;
++ struct wl_priv_signal destroy_signal;
++};
++
++struct wl_protocol_logger {
++ struct wl_list link;
++ wl_protocol_logger_func_t func;
++ void *user_data;
++};
++
++static int debug_server = 0;
++
++static void
++log_closure(struct wl_resource *resource,
++ struct wl_closure *closure, int send)
++{
++ struct wl_object *object = &resource->object;
++ struct wl_display *display = resource->client->display;
++ struct wl_protocol_logger *protocol_logger;
++ struct wl_protocol_logger_message message;
++
++ if (debug_server)
++ wl_closure_print(closure, object, send, false, NULL);
++
++ if (!wl_list_empty(&display->protocol_loggers)) {
++ message.resource = resource;
++ message.message_opcode = closure->opcode;
++ message.message = closure->message;
++ message.arguments_count = closure->count;
++ message.arguments = closure->args;
++ wl_list_for_each(protocol_logger,
++ &display->protocol_loggers, link) {
++ protocol_logger->func(protocol_logger->user_data,
++ send ? WL_PROTOCOL_LOGGER_EVENT :
++ WL_PROTOCOL_LOGGER_REQUEST,
++ &message);
++ }
++ }
++}
++
++static bool
++verify_objects(struct wl_resource *resource, uint32_t opcode,
++ union wl_argument *args)
++{
++ struct wl_object *object = &resource->object;
++ const char *signature = object->interface->events[opcode].signature;
++ struct argument_details arg;
++ struct wl_resource *res;
++ int count, i;
++
++ count = arg_count_for_signature(signature);
++ for (i = 0; i < count; i++) {
++ signature = get_next_argument(signature, &arg);
++ switch (arg.type) {
++ case 'n':
++ case 'o':
++ res = (struct wl_resource *) (args[i].o);
++ if (res && res->client != resource->client) {
++ wl_log("compositor bug: The compositor "
++ "tried to use an object from one "
++ "client in a '%s.%s' for a different "
++ "client.\n", object->interface->name,
++ object->interface->events[opcode].name);
++ return false;
++ }
++ }
++ }
++ return true;
++}
++
++static void
++handle_array(struct wl_resource *resource, uint32_t opcode,
++ union wl_argument *args,
++ int (*send_func)(struct wl_closure *, struct wl_connection *))
++{
++ struct wl_closure *closure;
++ struct wl_object *object = &resource->object;
++
++ if (resource->client->error)
++ return;
++
++ if (!verify_objects(resource, opcode, args)) {
++ resource->client->error = 1;
++ return;
++ }
++
++ closure = wl_closure_marshal(object, opcode, args,
++ &object->interface->events[opcode]);
++
++ if (closure == NULL) {
++ resource->client->error = 1;
++ return;
++ }
++
++ log_closure(resource, closure, true);
++
++ if (send_func(closure, resource->client->connection))
++ resource->client->error = 1;
++
++ wl_closure_destroy(closure);
++}
++
++WL_EXPORT void
++wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode,
++ union wl_argument *args)
++{
++ handle_array(resource, opcode, args, wl_closure_send);
++}
++
++WL_EXPORT void
++wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...)
++{
++ union wl_argument args[WL_CLOSURE_MAX_ARGS];
++ struct wl_object *object = &resource->object;
++ va_list ap;
++
++ va_start(ap, opcode);
++ wl_argument_from_va_list(object->interface->events[opcode].signature,
++ args, WL_CLOSURE_MAX_ARGS, ap);
++ va_end(ap);
++
++ wl_resource_post_event_array(resource, opcode, args);
++}
++
++
++WL_EXPORT void
++wl_resource_queue_event_array(struct wl_resource *resource, uint32_t opcode,
++ union wl_argument *args)
++{
++ handle_array(resource, opcode, args, wl_closure_queue);
++}
++
++WL_EXPORT void
++wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...)
++{
++ union wl_argument args[WL_CLOSURE_MAX_ARGS];
++ struct wl_object *object = &resource->object;
++ va_list ap;
++
++ va_start(ap, opcode);
++ wl_argument_from_va_list(object->interface->events[opcode].signature,
++ args, WL_CLOSURE_MAX_ARGS, ap);
++ va_end(ap);
++
++ wl_resource_queue_event_array(resource, opcode, args);
++}
++
++static void
++wl_resource_post_error_vargs(struct wl_resource *resource,
++ uint32_t code, const char *msg, va_list argp)
++{
++ struct wl_client *client = resource->client;
++ char buffer[128];
++
++ vsnprintf(buffer, sizeof buffer, msg, argp);
++
++ /*
++ * When a client aborts, its resources are destroyed in id order,
++ * which means the display resource is destroyed first. If destruction
++ * of any later resources results in a protocol error, we end up here
++ * with a NULL display_resource. Do not try to send errors to an
++ * already dead client.
++ */
++ if (client->error || !client->display_resource)
++ return;
++
++ wl_resource_post_event(client->display_resource,
++ WL_DISPLAY_ERROR, resource, code, buffer);
++ client->error = 1;
++
++}
++
++WL_EXPORT void
++wl_resource_post_error(struct wl_resource *resource,
++ uint32_t code, const char *msg, ...)
++{
++ va_list ap;
++
++ va_start(ap, msg);
++ wl_resource_post_error_vargs(resource, code, msg, ap);
++ va_end(ap);
++}
++
++static void
++destroy_client_with_error(struct wl_client *client, const char *reason)
++{
++ wl_log("%s (pid %u)\n", reason, client->pid);
++ wl_client_destroy(client);
++}
++
++static int
++wl_client_connection_data(int fd, uint32_t mask, void *data)
++{
++ struct wl_client *client = data;
++ struct wl_connection *connection = client->connection;
++ struct wl_resource *resource;
++ struct wl_object *object;
++ struct wl_closure *closure;
++ const struct wl_message *message;
++ uint32_t p[2];
++ uint32_t resource_flags;
++ int opcode, size, since;
++ int len;
++
++ if (mask & WL_EVENT_HANGUP) {
++ wl_client_destroy(client);
++ return 1;
++ }
++
++ if (mask & WL_EVENT_ERROR) {
++ destroy_client_with_error(client, "socket error");
++ return 1;
++ }
++
++ if (mask & WL_EVENT_WRITABLE) {
++ len = wl_connection_flush(connection);
++ if (len < 0 && errno != EAGAIN) {
++ destroy_client_with_error(
++ client, "failed to flush client connection");
++ return 1;
++ } else if (len >= 0) {
++ wl_event_source_fd_update(client->source,
++ WL_EVENT_READABLE);
++ }
++ }
++
++ len = 0;
++ if (mask & WL_EVENT_READABLE) {
++ len = wl_connection_read(connection);
++ if (len == 0 || (len < 0 && errno != EAGAIN)) {
++ destroy_client_with_error(
++ client, "failed to read client connection");
++ return 1;
++ }
++ }
++
++ while (len >= 0 && (size_t) len >= sizeof p) {
++ wl_connection_copy(connection, p, sizeof p);
++ opcode = p[1] & 0xffff;
++ size = p[1] >> 16;
++ if (len < size)
++ break;
++
++ resource = wl_map_lookup(&client->objects, p[0]);
++ resource_flags = wl_map_lookup_flags(&client->objects, p[0]);
++ if (resource == NULL) {
++ wl_resource_post_error(client->display_resource,
++ WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "invalid object %u", p[0]);
++ break;
++ }
++
++ object = &resource->object;
++ if (opcode >= object->interface->method_count) {
++ wl_resource_post_error(client->display_resource,
++ WL_DISPLAY_ERROR_INVALID_METHOD,
++ "invalid method %d, object %s@%u",
++ opcode,
++ object->interface->name,
++ object->id);
++ break;
++ }
++
++ message = &object->interface->methods[opcode];
++ since = wl_message_get_since(message);
++ if (!(resource_flags & WL_MAP_ENTRY_LEGACY) &&
++ resource->version > 0 && resource->version < since) {
++ wl_resource_post_error(client->display_resource,
++ WL_DISPLAY_ERROR_INVALID_METHOD,
++ "invalid method %d (since %d < %d)"
++ ", object %s@%u",
++ opcode, resource->version, since,
++ object->interface->name,
++ object->id);
++ break;
++ }
++
++
++ closure = wl_connection_demarshal(client->connection, size,
++ &client->objects, message);
++
++ if (closure == NULL && errno == ENOMEM) {
++ wl_resource_post_no_memory(resource);
++ break;
++ } else if (closure == NULL ||
++ wl_closure_lookup_objects(closure, &client->objects) < 0) {
++ wl_resource_post_error(client->display_resource,
++ WL_DISPLAY_ERROR_INVALID_METHOD,
++ "invalid arguments for %s@%u.%s",
++ object->interface->name,
++ object->id,
++ message->name);
++ wl_closure_destroy(closure);
++ break;
++ }
++
++ log_closure(resource, closure, false);
++
++ if ((resource_flags & WL_MAP_ENTRY_LEGACY) ||
++ resource->dispatcher == NULL) {
++ wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER,
++ object, opcode, client);
++ } else {
++ wl_closure_dispatch(closure, resource->dispatcher,
++ object, opcode);
++ }
++
++ wl_closure_destroy(closure);
++
++ if (client->error)
++ break;
++
++ len = wl_connection_pending_input(connection);
++ }
++
++ if (client->error) {
++ destroy_client_with_error(client,
++ "error in client communication");
++ }
++
++ return 1;
++}
++
++/** Flush pending events to the client
++ *
++ * \param client The client object
++ *
++ * Events sent to clients are queued in a buffer and written to the
++ * socket later - typically when the compositor has handled all
++ * requests and goes back to block in the event loop. This function
++ * flushes all queued up events for a client immediately.
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT void
++wl_client_flush(struct wl_client *client)
++{
++ wl_connection_flush(client->connection);
++}
++
++/** Get the display object for the given client
++ *
++ * \param client The client object
++ * \return The display object the client is associated with.
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT struct wl_display *
++wl_client_get_display(struct wl_client *client)
++{
++ return client->display;
++}
++
++static int
++bind_display(struct wl_client *client, struct wl_display *display);
++
++/** Create a client for the given file descriptor
++ *
++ * \param display The display object
++ * \param fd The file descriptor for the socket to the client
++ * \return The new client object or NULL on failure.
++ *
++ * Given a file descriptor corresponding to one end of a socket, this
++ * function will create a wl_client struct and add the new client to
++ * the compositors client list. At that point, the client is
++ * initialized and ready to run, as if the client had connected to the
++ * servers listening socket. When the client eventually sends
++ * requests to the compositor, the wl_client argument to the request
++ * handler will be the wl_client returned from this function.
++ *
++ * The other end of the socket can be passed to
++ * wl_display_connect_to_fd() on the client side or used with the
++ * WAYLAND_SOCKET environment variable on the client side.
++ *
++ * Listeners added with wl_display_add_client_created_listener() will
++ * be notified by this function after the client is fully constructed.
++ *
++ * On failure this function sets errno accordingly and returns NULL.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT struct wl_client *
++wl_client_create(struct wl_display *display, int fd)
++{
++ struct wl_client *client;
++
++ client = zalloc(sizeof *client);
++ if (client == NULL)
++ return NULL;
++
++ wl_priv_signal_init(&client->resource_created_signal);
++ client->display = display;
++ client->source = wl_event_loop_add_fd(display->loop, fd,
++ WL_EVENT_READABLE,
++ wl_client_connection_data, client);
++
++ if (!client->source)
++ goto err_client;
++
++ if (wl_os_socket_peercred(fd, &client->uid, &client->gid,
++ &client->pid) != 0)
++ goto err_source;
++
++ client->connection = wl_connection_create(fd);
++ if (client->connection == NULL)
++ goto err_source;
++
++ wl_map_init(&client->objects, WL_MAP_SERVER_SIDE);
++
++ if (wl_map_insert_at(&client->objects, 0, 0, NULL) < 0)
++ goto err_map;
++
++ wl_priv_signal_init(&client->destroy_signal);
++ if (bind_display(client, display) < 0)
++ goto err_map;
++
++ wl_list_insert(display->client_list.prev, &client->link);
++
++ wl_priv_signal_emit(&display->create_client_signal, client);
++
++ return client;
++
++err_map:
++ wl_map_release(&client->objects);
++ wl_connection_destroy(client->connection);
++err_source:
++ wl_event_source_remove(client->source);
++err_client:
++ free(client);
++ return NULL;
++}
++
++/** Return Unix credentials for the client
++ *
++ * \param client The display object
++ * \param pid Returns the process ID
++ * \param uid Returns the user ID
++ * \param gid Returns the group ID
++ *
++ * This function returns the process ID, the user ID and the group ID
++ * for the given client. The credentials come from getsockopt() with
++ * SO_PEERCRED, on the client socket fd. All the pointers can be
++ * NULL, if the caller is not interested in a particular ID.
++ *
++ * Note, process IDs are subject to race conditions and are not a reliable way
++ * to identify a client.
++ *
++ * Be aware that for clients that a compositor forks and execs and
++ * then connects using socketpair(), this function will return the
++ * credentials for the compositor. The credentials for the socketpair
++ * are set at creation time in the compositor.
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT void
++wl_client_get_credentials(struct wl_client *client,
++ pid_t *pid, uid_t *uid, gid_t *gid)
++{
++ if (pid)
++ *pid = client->pid;
++ if (uid)
++ *uid = client->uid;
++ if (gid)
++ *gid = client->gid;
++}
++
++/** Get the file descriptor for the client
++ *
++ * \param client The display object
++ * \return The file descriptor to use for the connection
++ *
++ * This function returns the file descriptor for the given client.
++ *
++ * Be sure to use the file descriptor from the client for inspection only.
++ * If the caller does anything to the file descriptor that changes its state,
++ * it will likely cause problems.
++ *
++ * See also wl_client_get_credentials().
++ * It is recommended that you evaluate whether wl_client_get_credentials()
++ * can be applied to your use case instead of this function.
++ *
++ * If you would like to distinguish just between the client and the compositor
++ * itself from the client's request, it can be done by getting the client
++ * credentials and by checking the PID of the client and the compositor's PID.
++ * Regarding the case in which the socketpair() is being used, you need to be
++ * careful. Please note the documentation for wl_client_get_credentials().
++ *
++ * This function can be used for a compositor to validate a request from
++ * a client if there are additional information provided from the client's
++ * file descriptor. For instance, suppose you can get the security contexts
++ * from the client's file descriptor. The compositor can validate the client's
++ * request with the contexts and make a decision whether it permits or deny it.
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT int
++wl_client_get_fd(struct wl_client *client)
++{
++ return wl_connection_get_fd(client->connection);
++}
++
++/** Look up an object in the client name space
++ *
++ * \param client The client object
++ * \param id The object id
++ * \return The object or NULL if there is not object for the given ID
++ *
++ * This looks up an object in the client object name space by its
++ * object ID.
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT struct wl_resource *
++wl_client_get_object(struct wl_client *client, uint32_t id)
++{
++ return wl_map_lookup(&client->objects, id);
++}
++
++WL_EXPORT void
++wl_client_post_no_memory(struct wl_client *client)
++{
++ wl_resource_post_error(client->display_resource,
++ WL_DISPLAY_ERROR_NO_MEMORY, "no memory");
++}
++
++/** Report an internal server error
++ *
++ * \param client The client object
++ * \param msg A printf-style format string
++ * \param ... Format string arguments
++ *
++ * Report an unspecified internal implementation error and disconnect
++ * the client.
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT void
++wl_client_post_implementation_error(struct wl_client *client,
++ char const *msg, ...)
++{
++ va_list ap;
++
++ va_start(ap, msg);
++ wl_resource_post_error_vargs(client->display_resource,
++ WL_DISPLAY_ERROR_IMPLEMENTATION,
++ msg, ap);
++ va_end(ap);
++}
++
++WL_EXPORT void
++wl_resource_post_no_memory(struct wl_resource *resource)
++{
++ wl_resource_post_error(resource->client->display_resource,
++ WL_DISPLAY_ERROR_NO_MEMORY, "no memory");
++}
++
++/** Detect if a wl_resource uses the deprecated public definition.
++ *
++ * Before Wayland 1.2.0, the definition of struct wl_resource was public.
++ * It was made opaque just before 1.2.0, and later new fields were added.
++ * The new fields cannot be accessed if a program is using the deprecated
++ * definition, as there would not be memory allocated for them.
++ *
++ * The creation pattern for the deprecated definition was wl_resource_init()
++ * followed by wl_client_add_resource(). wl_resource_init() was an inline
++ * function and no longer exists, but binaries might still carry it.
++ * wl_client_add_resource() still exists for ABI compatibility.
++ */
++static bool
++resource_is_deprecated(struct wl_resource *resource)
++{
++ struct wl_map *map = &resource->client->objects;
++ int id = resource->object.id;
++
++ /* wl_client_add_resource() marks deprecated resources with the flag. */
++ if (wl_map_lookup_flags(map, id) & WL_MAP_ENTRY_LEGACY)
++ return true;
++
++ return false;
++}
++
++static enum wl_iterator_result
++destroy_resource(void *element, void *data, uint32_t flags)
++{
++ struct wl_resource *resource = element;
++
++ wl_signal_emit(&resource->deprecated_destroy_signal, resource);
++ /* Don't emit the new signal for deprecated resources, as that would
++ * access memory outside the bounds of the deprecated struct */
++ if (!resource_is_deprecated(resource))
++ wl_priv_signal_final_emit(&resource->destroy_signal, resource);
++
++ if (resource->destroy)
++ resource->destroy(resource);
++
++ if (!(flags & WL_MAP_ENTRY_LEGACY))
++ free(resource);
++
++ return WL_ITERATOR_CONTINUE;
++}
++
++WL_EXPORT void
++wl_resource_destroy(struct wl_resource *resource)
++{
++ struct wl_client *client = resource->client;
++ uint32_t id;
++ uint32_t flags;
++
++ id = resource->object.id;
++ flags = wl_map_lookup_flags(&client->objects, id);
++ destroy_resource(resource, NULL, flags);
++
++ if (id < WL_SERVER_ID_START) {
++ if (client->display_resource) {
++ wl_resource_queue_event(client->display_resource,
++ WL_DISPLAY_DELETE_ID, id);
++ }
++ wl_map_insert_at(&client->objects, 0, id, NULL);
++ } else {
++ wl_map_remove(&client->objects, id);
++ }
++}
++
++WL_EXPORT uint32_t
++wl_resource_get_id(struct wl_resource *resource)
++{
++ return resource->object.id;
++}
++
++WL_EXPORT struct wl_list *
++wl_resource_get_link(struct wl_resource *resource)
++{
++ return &resource->link;
++}
++
++WL_EXPORT struct wl_resource *
++wl_resource_from_link(struct wl_list *link)
++{
++ struct wl_resource *resource;
++
++ return wl_container_of(link, resource, link);
++}
++
++WL_EXPORT struct wl_resource *
++wl_resource_find_for_client(struct wl_list *list, struct wl_client *client)
++{
++ struct wl_resource *resource;
++
++ if (client == NULL)
++ return NULL;
++
++ wl_list_for_each(resource, list, link) {
++ if (resource->client == client)
++ return resource;
++ }
++
++ return NULL;
++}
++
++WL_EXPORT struct wl_client *
++wl_resource_get_client(struct wl_resource *resource)
++{
++ return resource->client;
++}
++
++WL_EXPORT void
++wl_resource_set_user_data(struct wl_resource *resource, void *data)
++{
++ resource->data = data;
++}
++
++WL_EXPORT void *
++wl_resource_get_user_data(struct wl_resource *resource)
++{
++ return resource->data;
++}
++
++WL_EXPORT int
++wl_resource_get_version(struct wl_resource *resource)
++{
++ return resource->version;
++}
++
++WL_EXPORT void
++wl_resource_set_destructor(struct wl_resource *resource,
++ wl_resource_destroy_func_t destroy)
++{
++ resource->destroy = destroy;
++}
++
++WL_EXPORT int
++wl_resource_instance_of(struct wl_resource *resource,
++ const struct wl_interface *interface,
++ const void *implementation)
++{
++ return wl_interface_equal(resource->object.interface, interface) &&
++ resource->object.implementation == implementation;
++}
++
++WL_EXPORT void
++wl_resource_add_destroy_listener(struct wl_resource *resource,
++ struct wl_listener * listener)
++{
++ if (resource_is_deprecated(resource))
++ wl_signal_add(&resource->deprecated_destroy_signal, listener);
++ else
++ wl_priv_signal_add(&resource->destroy_signal, listener);
++}
++
++WL_EXPORT struct wl_listener *
++wl_resource_get_destroy_listener(struct wl_resource *resource,
++ wl_notify_func_t notify)
++{
++ if (resource_is_deprecated(resource))
++ return wl_signal_get(&resource->deprecated_destroy_signal, notify);
++ return wl_priv_signal_get(&resource->destroy_signal, notify);
++}
++
++/** Retrieve the interface name (class) of a resource object.
++ *
++ * \param resource The resource object
++ *
++ * \memberof wl_resource
++ */
++WL_EXPORT const char *
++wl_resource_get_class(struct wl_resource *resource)
++{
++ return resource->object.interface->name;
++}
++
++WL_EXPORT void
++wl_client_add_destroy_listener(struct wl_client *client,
++ struct wl_listener *listener)
++{
++ wl_priv_signal_add(&client->destroy_signal, listener);
++}
++
++WL_EXPORT struct wl_listener *
++wl_client_get_destroy_listener(struct wl_client *client,
++ wl_notify_func_t notify)
++{
++ return wl_priv_signal_get(&client->destroy_signal, notify);
++}
++
++WL_EXPORT void
++wl_client_destroy(struct wl_client *client)
++{
++ uint32_t serial = 0;
++
++ wl_priv_signal_final_emit(&client->destroy_signal, client);
++
++ wl_client_flush(client);
++ wl_map_for_each(&client->objects, destroy_resource, &serial);
++ wl_map_release(&client->objects);
++ wl_event_source_remove(client->source);
++ close(wl_connection_destroy(client->connection));
++ wl_list_remove(&client->link);
++ wl_list_remove(&client->resource_created_signal.listener_list);
++ free(client);
++}
++
++/* Check if a global filter is registered and use it if any.
++ *
++ * If no wl_global filter has been registered, this function will
++ * return true, allowing the wl_global to be visible to the wl_client
++ */
++static bool
++wl_global_is_visible(const struct wl_client *client,
++ const struct wl_global *global)
++{
++ struct wl_display *display = client->display;
++
++ return (display->global_filter == NULL ||
++ display->global_filter(client, global, display->global_filter_data));
++}
++
++static void
++registry_bind(struct wl_client *client,
++ struct wl_resource *resource, uint32_t name,
++ const char *interface, uint32_t version, uint32_t id)
++{
++ struct wl_global *global;
++ struct wl_display *display = resource->data;
++
++ wl_list_for_each(global, &display->global_list, link)
++ if (global->name == name)
++ break;
++
++ if (&global->link == &display->global_list)
++ wl_resource_post_error(resource,
++ WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "invalid global %s (%d)", interface, name);
++ else if (strcmp(global->interface->name, interface) != 0)
++ wl_resource_post_error(resource,
++ WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "invalid interface for global %u: "
++ "have %s, wanted %s",
++ name, interface, global->interface->name);
++ else if (version == 0)
++ wl_resource_post_error(resource,
++ WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "invalid version for global %s (%d): 0 is not a valid version",
++ interface, name);
++ else if (global->version < version)
++ wl_resource_post_error(resource,
++ WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "invalid version for global %s (%d): have %d, wanted %d",
++ interface, name, global->version, version);
++ else if (!wl_global_is_visible(client, global))
++ wl_resource_post_error(resource,
++ WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "invalid global %s (%d)", interface, name);
++ else
++ global->bind(client, global->data, version, id);
++}
++
++static const struct wl_registry_interface registry_interface = {
++ registry_bind
++};
++
++static void
++display_sync(struct wl_client *client,
++ struct wl_resource *resource, uint32_t id)
++{
++ struct wl_resource *callback;
++ uint32_t serial;
++
++ callback = wl_resource_create(client, &wl_callback_interface, 1, id);
++ if (callback == NULL) {
++ wl_client_post_no_memory(client);
++ return;
++ }
++
++ serial = wl_display_get_serial(client->display);
++ wl_callback_send_done(callback, serial);
++ wl_resource_destroy(callback);
++}
++
++static void
++unbind_resource(struct wl_resource *resource)
++{
++ wl_list_remove(&resource->link);
++}
++
++static void
++display_get_registry(struct wl_client *client,
++ struct wl_resource *resource, uint32_t id)
++{
++ struct wl_display *display = resource->data;
++ struct wl_resource *registry_resource;
++ struct wl_global *global;
++
++ registry_resource =
++ wl_resource_create(client, &wl_registry_interface, 1, id);
++ if (registry_resource == NULL) {
++ wl_client_post_no_memory(client);
++ return;
++ }
++
++ wl_resource_set_implementation(registry_resource,
++ ®istry_interface,
++ display, unbind_resource);
++
++ wl_list_insert(&display->registry_resource_list,
++ ®istry_resource->link);
++
++ wl_list_for_each(global, &display->global_list, link)
++ if (wl_global_is_visible(client, global) && !global->removed)
++ wl_resource_post_event(registry_resource,
++ WL_REGISTRY_GLOBAL,
++ global->name,
++ global->interface->name,
++ global->version);
++}
++
++static const struct wl_display_interface display_interface = {
++ display_sync,
++ display_get_registry
++};
++
++static void
++destroy_client_display_resource(struct wl_resource *resource)
++{
++ resource->client->display_resource = NULL;
++}
++
++static int
++bind_display(struct wl_client *client, struct wl_display *display)
++{
++ client->display_resource =
++ wl_resource_create(client, &wl_display_interface, 1, 1);
++ if (client->display_resource == NULL) {
++ /* DON'T send no-memory error to client - it has no
++ * resource to which it could post the event */
++ return -1;
++ }
++
++ wl_resource_set_implementation(client->display_resource,
++ &display_interface, display,
++ destroy_client_display_resource);
++ return 0;
++}
++
++static int
++handle_display_terminate(int fd, uint32_t mask, void *data) {
++ uint64_t term_event;
++
++ if (read(fd, &term_event, sizeof(term_event)) < 0 && errno != EAGAIN)
++ return -1;
++
++ return 0;
++}
++
++/** Create Wayland display object.
++ *
++ * \return The Wayland display object. Null if failed to create
++ *
++ * This creates the wl_display object.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT struct wl_display *
++wl_display_create(void)
++{
++ struct wl_display *display;
++ const char *debug;
++
++ debug = getenv("WAYLAND_DEBUG");
++ if (debug && (strstr(debug, "server") || strstr(debug, "1")))
++ debug_server = 1;
++
++ display = zalloc(sizeof *display);
++ if (display == NULL)
++ return NULL;
++
++ display->loop = wl_event_loop_create();
++ if (display->loop == NULL) {
++ free(display);
++ return NULL;
++ }
++
++ display->terminate_efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
++ if (display->terminate_efd < 0)
++ goto err_eventfd;
++
++ display->term_source = wl_event_loop_add_fd(display->loop,
++ display->terminate_efd,
++ WL_EVENT_READABLE,
++ handle_display_terminate,
++ NULL);
++
++ if (display->term_source == NULL)
++ goto err_term_source;
++
++ wl_list_init(&display->global_list);
++ wl_list_init(&display->socket_list);
++ wl_list_init(&display->client_list);
++ wl_list_init(&display->registry_resource_list);
++ wl_list_init(&display->protocol_loggers);
++
++ wl_priv_signal_init(&display->destroy_signal);
++ wl_priv_signal_init(&display->create_client_signal);
++
++ display->id = 1;
++ display->serial = 0;
++
++ display->global_filter = NULL;
++ display->global_filter_data = NULL;
++
++ wl_array_init(&display->additional_shm_formats);
++
++ return display;
++
++err_term_source:
++ close(display->terminate_efd);
++err_eventfd:
++ wl_event_loop_destroy(display->loop);
++ free(display);
++ return NULL;
++}
++
++static void
++wl_socket_destroy(struct wl_socket *s)
++{
++ if (s->source)
++ wl_event_source_remove(s->source);
++ if (s->addr.sun_path[0])
++ unlink(s->addr.sun_path);
++ if (s->fd >= 0)
++ close(s->fd);
++ if (s->lock_addr[0])
++ unlink(s->lock_addr);
++ if (s->fd_lock >= 0)
++ close(s->fd_lock);
++
++ free(s);
++}
++
++static struct wl_socket *
++wl_socket_alloc(void)
++{
++ struct wl_socket *s;
++
++ s = zalloc(sizeof *s);
++ if (!s)
++ return NULL;
++
++ s->fd = -1;
++ s->fd_lock = -1;
++
++ return s;
++}
++
++/** Destroy Wayland display object.
++ *
++ * \param display The Wayland display object which should be destroyed.
++ * \return None.
++ *
++ * This function emits the wl_display destroy signal, releases
++ * all the sockets added to this display, free's all the globals associated
++ * with this display, free's memory of additional shared memory formats and
++ * destroy the display object.
++ *
++ * \sa wl_display_add_destroy_listener
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT void
++wl_display_destroy(struct wl_display *display)
++{
++ struct wl_socket *s, *next;
++ struct wl_global *global, *gnext;
++
++ wl_priv_signal_final_emit(&display->destroy_signal, display);
++
++ wl_list_for_each_safe(s, next, &display->socket_list, link) {
++ wl_socket_destroy(s);
++ }
++
++ close(display->terminate_efd);
++ wl_event_source_remove(display->term_source);
++
++ wl_event_loop_destroy(display->loop);
++
++ wl_list_for_each_safe(global, gnext, &display->global_list, link)
++ free(global);
++
++ wl_array_release(&display->additional_shm_formats);
++
++ wl_list_remove(&display->protocol_loggers);
++
++ free(display);
++}
++
++/** Set a filter function for global objects
++ *
++ * \param display The Wayland display object.
++ * \param filter The global filter function.
++ * \param data User data to be associated with the global filter.
++ * \return None.
++ *
++ * Set a filter for the wl_display to advertise or hide global objects
++ * to clients.
++ * The set filter will be used during wl_global advertisement to
++ * determine whether a global object should be advertised to a
++ * given client, and during wl_global binding to determine whether
++ * a given client should be allowed to bind to a global.
++ *
++ * Clients that try to bind to a global that was filtered out will
++ * have an error raised.
++ *
++ * Setting the filter NULL will result in all globals being
++ * advertised to all clients. The default is no filter.
++ *
++ * The filter should be installed before any client connects and should always
++ * take the same decision given a client and a global. Not doing so will result
++ * in inconsistent filtering and broken wl_registry event sequences.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT void
++wl_display_set_global_filter(struct wl_display *display,
++ wl_display_global_filter_func_t filter,
++ void *data)
++{
++ display->global_filter = filter;
++ display->global_filter_data = data;
++}
++
++WL_EXPORT struct wl_global *
++wl_global_create(struct wl_display *display,
++ const struct wl_interface *interface, int version,
++ void *data, wl_global_bind_func_t bind)
++{
++ struct wl_global *global;
++ struct wl_resource *resource;
++
++ if (version < 1) {
++ wl_log("wl_global_create: failing to create interface "
++ "'%s' with version %d because it is less than 1\n",
++ interface->name, version);
++ return NULL;
++ }
++
++ if (version > interface->version) {
++ wl_log("wl_global_create: implemented version for '%s' "
++ "higher than interface version (%d > %d)\n",
++ interface->name, version, interface->version);
++ return NULL;
++ }
++
++ global = zalloc(sizeof *global);
++ if (global == NULL)
++ return NULL;
++
++ global->display = display;
++ global->name = display->id++;
++ global->interface = interface;
++ global->version = version;
++ global->data = data;
++ global->bind = bind;
++ global->removed = false;
++ wl_list_insert(display->global_list.prev, &global->link);
++
++ wl_list_for_each(resource, &display->registry_resource_list, link)
++ if (wl_global_is_visible(resource->client, global))
++ wl_resource_post_event(resource,
++ WL_REGISTRY_GLOBAL,
++ global->name,
++ global->interface->name,
++ global->version);
++
++ return global;
++}
++
++/** Remove the global
++ *
++ * \param global The Wayland global.
++ *
++ * Broadcast a global remove event to all clients without destroying the
++ * global. This function can only be called once per global.
++ *
++ * wl_global_destroy() removes the global and immediately destroys it. On
++ * the other end, this function only removes the global, allowing clients
++ * that have not yet received the global remove event to continue to bind to
++ * it.
++ *
++ * This can be used by compositors to mitigate clients being disconnected
++ * because a global has been added and removed too quickly. Compositors can call
++ * wl_global_remove(), then wait an implementation-defined amount of time, then
++ * call wl_global_destroy(). Note that the destruction of a global is still
++ * racy, since clients have no way to acknowledge that they received the remove
++ * event.
++ *
++ * \since 1.17.90
++ */
++WL_EXPORT void
++wl_global_remove(struct wl_global *global)
++{
++ struct wl_display *display = global->display;
++ struct wl_resource *resource;
++
++ if (global->removed)
++ wl_abort("wl_global_remove: called twice on the same "
++ "global '%s@%"PRIu32"'", global->interface->name,
++ global->name);
++
++ wl_list_for_each(resource, &display->registry_resource_list, link)
++ if (wl_global_is_visible(resource->client, global))
++ wl_resource_post_event(resource, WL_REGISTRY_GLOBAL_REMOVE,
++ global->name);
++
++ global->removed = true;
++}
++
++WL_EXPORT void
++wl_global_destroy(struct wl_global *global)
++{
++ if (!global->removed)
++ wl_global_remove(global);
++ wl_list_remove(&global->link);
++ free(global);
++}
++
++WL_EXPORT const struct wl_interface *
++wl_global_get_interface(const struct wl_global *global)
++{
++ return global->interface;
++}
++
++/** Get the version of the given global.
++ *
++ * \param global The global object.
++ * \return The version advertised by the global.
++ *
++ * \memberof wl_global
++ * \since 1.21
++ */
++WL_EXPORT uint32_t
++wl_global_get_version(const struct wl_global *global)
++{
++ return global->version;
++}
++
++/** Get the display object for the given global
++ *
++ * \param global The global object
++ * \return The display object the global is associated with.
++ *
++ * \memberof wl_global
++ * \since 1.20
++ */
++WL_EXPORT struct wl_display *
++wl_global_get_display(const struct wl_global *global)
++{
++ return global->display;
++}
++
++WL_EXPORT void *
++wl_global_get_user_data(const struct wl_global *global)
++{
++ return global->data;
++}
++
++/** Set the global's user data
++ *
++ * \param global The global object
++ * \param data The user data pointer
++ *
++ * \since 1.17.90
++ */
++WL_EXPORT void
++wl_global_set_user_data(struct wl_global *global, void *data)
++{
++ global->data = data;
++}
++
++/** Get the current serial number
++ *
++ * \param display The display object
++ *
++ * This function returns the most recent serial number, but does not
++ * increment it.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT uint32_t
++wl_display_get_serial(struct wl_display *display)
++{
++ return display->serial;
++}
++
++/** Get the next serial number
++ *
++ * \param display The display object
++ *
++ * This function increments the display serial number and returns the
++ * new value.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT uint32_t
++wl_display_next_serial(struct wl_display *display)
++{
++ display->serial++;
++
++ return display->serial;
++}
++
++WL_EXPORT struct wl_event_loop *
++wl_display_get_event_loop(struct wl_display *display)
++{
++ return display->loop;
++}
++
++WL_EXPORT void
++wl_display_terminate(struct wl_display *display)
++{
++ int ret;
++ uint64_t terminate = 1;
++
++ display->run = 0;
++
++ ret = write(display->terminate_efd, &terminate, sizeof(terminate));
++ assert (ret >= 0 || errno == EAGAIN);
++}
++
++WL_EXPORT void
++wl_display_run(struct wl_display *display)
++{
++ display->run = 1;
++
++ while (display->run) {
++ wl_display_flush_clients(display);
++ wl_event_loop_dispatch(display->loop, -1);
++ }
++}
++
++WL_EXPORT void
++wl_display_flush_clients(struct wl_display *display)
++{
++ struct wl_client *client, *next;
++ int ret;
++
++ wl_list_for_each_safe(client, next, &display->client_list, link) {
++ ret = wl_connection_flush(client->connection);
++ if (ret < 0 && errno == EAGAIN) {
++ wl_event_source_fd_update(client->source,
++ WL_EVENT_WRITABLE |
++ WL_EVENT_READABLE);
++ } else if (ret < 0) {
++ wl_client_destroy(client);
++ }
++ }
++}
++
++/** Destroy all clients connected to the display
++ *
++ * \param display The display object
++ *
++ * This function should be called right before wl_display_destroy() to ensure
++ * all client resources are closed properly. Destroying a client from within
++ * wl_display_destroy_clients() is safe, but creating one will leak resources
++ * and raise a warning.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT void
++wl_display_destroy_clients(struct wl_display *display)
++{
++ struct wl_list tmp_client_list, *pos;
++ struct wl_client *client;
++
++ /* Move the whole client list to a temporary head because some new clients
++ * might be added to the original head. */
++ wl_list_init(&tmp_client_list);
++ wl_list_insert_list(&tmp_client_list, &display->client_list);
++ wl_list_init(&display->client_list);
++
++ /* wl_list_for_each_safe isn't enough here: it fails if the next client is
++ * destroyed by the destroy handler of the current one. */
++ while (!wl_list_empty(&tmp_client_list)) {
++ pos = tmp_client_list.next;
++ client = wl_container_of(pos, client, link);
++
++ wl_client_destroy(client);
++ }
++
++ if (!wl_list_empty(&display->client_list)) {
++ wl_log("wl_display_destroy_clients: cannot destroy all clients because "
++ "new ones were created by destroy callbacks\n");
++ }
++}
++
++static int
++socket_data(int fd, uint32_t mask, void *data)
++{
++ struct wl_display *display = data;
++ struct sockaddr_un name;
++ socklen_t length;
++ int client_fd;
++
++ length = sizeof name;
++ client_fd = wl_os_accept_cloexec(fd, (struct sockaddr *) &name,
++ &length);
++ if (client_fd < 0)
++ wl_log("failed to accept: %s\n", strerror(errno));
++ else
++ if (!wl_client_create(display, client_fd))
++ close(client_fd);
++
++ return 1;
++}
++
++static int
++wl_socket_lock(struct wl_socket *socket)
++{
++ struct stat socket_stat;
++
++ snprintf(socket->lock_addr, sizeof socket->lock_addr,
++ "%s%s", socket->addr.sun_path, LOCK_SUFFIX);
++
++ socket->fd_lock = open(socket->lock_addr, O_CREAT | O_CLOEXEC | O_RDWR,
++ (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
++
++ if (socket->fd_lock < 0) {
++ wl_log("unable to open lockfile %s check permissions\n",
++ socket->lock_addr);
++ goto err;
++ }
++
++ if (flock(socket->fd_lock, LOCK_EX | LOCK_NB) < 0) {
++ wl_log("unable to lock lockfile %s, maybe another compositor is running\n",
++ socket->lock_addr);
++ goto err_fd;
++ }
++
++ if (lstat(socket->addr.sun_path, &socket_stat) < 0 ) {
++ if (errno != ENOENT) {
++ wl_log("did not manage to stat file %s\n",
++ socket->addr.sun_path);
++ goto err_fd;
++ }
++ } else if (socket_stat.st_mode & S_IWUSR ||
++ socket_stat.st_mode & S_IWGRP) {
++ unlink(socket->addr.sun_path);
++ }
++
++ return 0;
++err_fd:
++ close(socket->fd_lock);
++ socket->fd_lock = -1;
++err:
++ *socket->lock_addr = 0;
++ /* we did not set this value here, but without lock the
++ * socket won't be created anyway. This prevents the
++ * wl_socket_destroy from unlinking already existing socket
++ * created by other compositor */
++ *socket->addr.sun_path = 0;
++
++ return -1;
++}
++
++static int
++wl_socket_init_for_display_name(struct wl_socket *s, const char *name)
++{
++ int name_size;
++ const char *runtime_dir = "";
++ const char *separator = "";
++
++ if (name[0] != '/') {
++ runtime_dir = getenv("XDG_RUNTIME_DIR");
++ if (!runtime_dir || runtime_dir[0] != '/') {
++ wl_log("error: XDG_RUNTIME_DIR is invalid or not set in"
++ " the environment\n");
++
++ /* to prevent programs reporting
++ * "failed to add socket: Success" */
++ errno = ENOENT;
++ return -1;
++ }
++ separator = "/";
++ }
++
++ s->addr.sun_family = AF_LOCAL;
++ name_size = snprintf(s->addr.sun_path, sizeof s->addr.sun_path,
++ "%s%s%s", runtime_dir, separator, name) + 1;
++
++ assert(name_size > 0);
++ if (name_size > (int)sizeof s->addr.sun_path) {
++ wl_log("error: socket path \"%s%s%s\" plus null terminator"
++ " exceeds 108 bytes\n", runtime_dir, separator, name);
++ *s->addr.sun_path = 0;
++ /* to prevent programs reporting
++ * "failed to add socket: Success" */
++ errno = ENAMETOOLONG;
++ return -1;
++ }
++
++ s->display_name = (s->addr.sun_path + name_size - 1) - strlen(name);
++
++ return 0;
++}
++
++static int
++_wl_display_add_socket(struct wl_display *display, struct wl_socket *s)
++{
++ socklen_t size;
++
++ s->fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
++ if (s->fd < 0) {
++ return -1;
++ }
++
++ size = offsetof (struct sockaddr_un, sun_path) + strlen(s->addr.sun_path);
++ if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) {
++ wl_log("bind() failed with error: %s\n", strerror(errno));
++ return -1;
++ }
++
++ if (listen(s->fd, 128) < 0) {
++ wl_log("listen() failed with error: %s\n", strerror(errno));
++ return -1;
++ }
++
++ s->source = wl_event_loop_add_fd(display->loop, s->fd,
++ WL_EVENT_READABLE,
++ socket_data, display);
++ if (s->source == NULL) {
++ return -1;
++ }
++
++ wl_list_insert(display->socket_list.prev, &s->link);
++ return 0;
++}
++
++WL_EXPORT const char *
++wl_display_add_socket_auto(struct wl_display *display)
++{
++ struct wl_socket *s;
++ int displayno = 0;
++ char display_name[20] = "";
++
++ /* A reasonable number of maximum default sockets. If
++ * you need more than this, use the explicit add_socket API. */
++ const int MAX_DISPLAYNO = 32;
++
++ s = wl_socket_alloc();
++ if (s == NULL)
++ return NULL;
++
++ do {
++ snprintf(display_name, sizeof display_name, "wayland-%d", displayno);
++ if (wl_socket_init_for_display_name(s, display_name) < 0) {
++ wl_socket_destroy(s);
++ return NULL;
++ }
++
++ if (wl_socket_lock(s) < 0)
++ continue;
++
++ if (_wl_display_add_socket(display, s) < 0) {
++ wl_socket_destroy(s);
++ return NULL;
++ }
++
++ return s->display_name;
++ } while (displayno++ < MAX_DISPLAYNO);
++
++ /* Ran out of display names. */
++ wl_socket_destroy(s);
++ errno = EINVAL;
++ return NULL;
++}
++
++/** Add a socket with an existing fd to Wayland display for the clients to connect.
++ *
++ * \param display Wayland display to which the socket should be added.
++ * \param sock_fd The existing socket file descriptor to be used
++ * \return 0 if success. -1 if failed.
++ *
++ * The existing socket fd must already be created, opened, and locked.
++ * The fd must be properly set to CLOEXEC and bound to a socket file
++ * with both bind() and listen() already called.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_add_socket_fd(struct wl_display *display, int sock_fd)
++{
++ struct wl_socket *s;
++ struct stat buf;
++
++ /* Require a valid fd or fail */
++ if (sock_fd < 0 || fstat(sock_fd, &buf) < 0 || !S_ISSOCK(buf.st_mode)) {
++ return -1;
++ }
++
++ s = wl_socket_alloc();
++ if (s == NULL)
++ return -1;
++
++ s->source = wl_event_loop_add_fd(display->loop, sock_fd,
++ WL_EVENT_READABLE,
++ socket_data, display);
++ if (s->source == NULL) {
++ wl_log("failed to establish event source\n");
++ wl_socket_destroy(s);
++ return -1;
++ }
++
++ /* Reuse the existing fd */
++ s->fd = sock_fd;
++
++ wl_list_insert(display->socket_list.prev, &s->link);
++
++ return 0;
++}
++
++/** Add a socket to Wayland display for the clients to connect.
++ *
++ * \param display Wayland display to which the socket should be added.
++ * \param name Name of the Unix socket.
++ * \return 0 if success. -1 if failed.
++ *
++ * This adds a Unix socket to Wayland display which can be used by clients to
++ * connect to Wayland display.
++ *
++ * If NULL is passed as name, then it would look for WAYLAND_DISPLAY env
++ * variable for the socket name. If WAYLAND_DISPLAY is not set, then default
++ * wayland-0 is used.
++ *
++ * If the socket name is a relative path, the Unix socket will be created in
++ * the directory pointed to by environment variable XDG_RUNTIME_DIR. If
++ * XDG_RUNTIME_DIR is invalid or not set, then this function fails and returns -1.
++ *
++ * If the socket name is an absolute path, then it is used as-is for the
++ * the Unix socket.
++ *
++ * The length of the computed socket path must not exceed the maximum length
++ * of a Unix socket path.
++ * The function also fails if the user does not have write permission in the
++ * directory or if the path is already in use.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_add_socket(struct wl_display *display, const char *name)
++{
++ struct wl_socket *s;
++
++ s = wl_socket_alloc();
++ if (s == NULL)
++ return -1;
++
++ if (name == NULL)
++ name = getenv("WAYLAND_DISPLAY");
++ if (name == NULL)
++ name = "wayland-0";
++
++ if (wl_socket_init_for_display_name(s, name) < 0) {
++ wl_socket_destroy(s);
++ return -1;
++ }
++
++ if (wl_socket_lock(s) < 0) {
++ wl_socket_destroy(s);
++ return -1;
++ }
++
++ if (_wl_display_add_socket(display, s) < 0) {
++ wl_socket_destroy(s);
++ return -1;
++ }
++
++ return 0;
++}
++
++WL_EXPORT void
++wl_display_add_destroy_listener(struct wl_display *display,
++ struct wl_listener *listener)
++{
++ wl_priv_signal_add(&display->destroy_signal, listener);
++}
++
++/** Registers a listener for the client connection signal.
++ * When a new client object is created, \a listener will be notified, carrying
++ * a pointer to the new wl_client object.
++ *
++ * \ref wl_client_create
++ * \ref wl_display
++ * \ref wl_listener
++ *
++ * \param display The display object
++ * \param listener Signal handler object
++ */
++WL_EXPORT void
++wl_display_add_client_created_listener(struct wl_display *display,
++ struct wl_listener *listener)
++{
++ wl_priv_signal_add(&display->create_client_signal, listener);
++}
++
++WL_EXPORT struct wl_listener *
++wl_display_get_destroy_listener(struct wl_display *display,
++ wl_notify_func_t notify)
++{
++ return wl_priv_signal_get(&display->destroy_signal, notify);
++}
++
++WL_EXPORT void
++wl_resource_set_implementation(struct wl_resource *resource,
++ const void *implementation,
++ void *data, wl_resource_destroy_func_t destroy)
++{
++ resource->object.implementation = implementation;
++ resource->data = data;
++ resource->destroy = destroy;
++ resource->dispatcher = NULL;
++}
++
++WL_EXPORT void
++wl_resource_set_dispatcher(struct wl_resource *resource,
++ wl_dispatcher_func_t dispatcher,
++ const void *implementation,
++ void *data, wl_resource_destroy_func_t destroy)
++{
++ resource->dispatcher = dispatcher;
++ resource->object.implementation = implementation;
++ resource->data = data;
++ resource->destroy = destroy;
++}
++
++/** Create a new resource object
++ *
++ * \param client The client owner of the new resource.
++ * \param interface The interface of the new resource.
++ * \param version The version of the new resource.
++ * \param id The id of the new resource. If 0, an available id will be used.
++ *
++ * Listeners added with \a wl_client_add_resource_created_listener will be
++ * notified at the end of this function.
++ *
++ * \memberof wl_resource
++ */
++WL_EXPORT struct wl_resource *
++wl_resource_create(struct wl_client *client,
++ const struct wl_interface *interface,
++ int version, uint32_t id)
++{
++ struct wl_resource *resource;
++
++ resource = zalloc(sizeof *resource);
++ if (resource == NULL)
++ return NULL;
++
++ if (id == 0) {
++ id = wl_map_insert_new(&client->objects, 0, NULL);
++ if (id == 0) {
++ free(resource);
++ return NULL;
++ }
++ }
++
++ resource->object.id = id;
++ resource->object.interface = interface;
++ resource->object.implementation = NULL;
++
++ wl_signal_init(&resource->deprecated_destroy_signal);
++ wl_priv_signal_init(&resource->destroy_signal);
++
++ resource->destroy = NULL;
++ resource->client = client;
++ resource->data = NULL;
++ resource->version = version;
++ resource->dispatcher = NULL;
++
++ if (wl_map_insert_at(&client->objects, 0, id, resource) < 0) {
++ if (errno == EINVAL) {
++ wl_resource_post_error(client->display_resource,
++ WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "invalid new id %d", id);
++ }
++ free(resource);
++ return NULL;
++ }
++
++ wl_priv_signal_emit(&client->resource_created_signal, resource);
++ return resource;
++}
++
++WL_EXPORT void
++wl_log_set_handler_server(wl_log_func_t handler)
++{
++ wl_log_handler = handler;
++}
++
++/** Adds a new protocol logger.
++ *
++ * When a new protocol message arrives or is sent from the server
++ * all the protocol logger functions will be called, carrying the
++ * \a user_data pointer, the type of the message (request or
++ * event) and the actual message.
++ * The lifetime of the messages passed to the logger function ends
++ * when they return so the messages cannot be stored and accessed
++ * later.
++ *
++ * \a errno is set on error.
++ *
++ * \param display The display object
++ * \param func The function to call to log a new protocol message
++ * \param user_data The user data pointer to pass to \a func
++ *
++ * \return The protol logger object on success, NULL on failure.
++ *
++ * \sa wl_protocol_logger_destroy
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT struct wl_protocol_logger *
++wl_display_add_protocol_logger(struct wl_display *display,
++ wl_protocol_logger_func_t func, void *user_data)
++{
++ struct wl_protocol_logger *logger;
++
++ logger = zalloc(sizeof *logger);
++ if (!logger)
++ return NULL;
++
++ logger->func = func;
++ logger->user_data = user_data;
++ wl_list_insert(&display->protocol_loggers, &logger->link);
++
++ return logger;
++}
++
++/** Destroys a protocol logger.
++ *
++ * This function destroys a protocol logger and removes it from the display
++ * it was added to with \a wl_display_add_protocol_logger.
++ * The \a logger object becomes invalid after calling this function.
++ *
++ * \sa wl_display_add_protocol_logger
++ *
++ * \memberof wl_protocol_logger
++ */
++WL_EXPORT void
++wl_protocol_logger_destroy(struct wl_protocol_logger *logger)
++{
++ wl_list_remove(&logger->link);
++ free(logger);
++}
++
++/** Add support for a wl_shm pixel format
++ *
++ * \param display The display object
++ * \param format The wl_shm pixel format to advertise
++ * \return A pointer to the wl_shm format that was added to the list
++ * or NULL if adding it to the list failed.
++ *
++ * Add the specified wl_shm format to the list of formats the wl_shm
++ * object advertises when a client binds to it. Adding a format to
++ * the list means that clients will know that the compositor supports
++ * this format and may use it for creating wl_shm buffers. The
++ * compositor must be able to handle the pixel format when a client
++ * requests it.
++ *
++ * The compositor by default supports WL_SHM_FORMAT_ARGB8888 and
++ * WL_SHM_FORMAT_XRGB8888.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT uint32_t *
++wl_display_add_shm_format(struct wl_display *display, uint32_t format)
++{
++ uint32_t *p = NULL;
++
++ p = wl_array_add(&display->additional_shm_formats, sizeof *p);
++
++ if (p != NULL)
++ *p = format;
++ return p;
++}
++
++/**
++ * Get list of additional wl_shm pixel formats
++ *
++ * \param display The display object
++ *
++ * This function returns the list of addition wl_shm pixel formats
++ * that the compositor supports. WL_SHM_FORMAT_ARGB8888 and
++ * WL_SHM_FORMAT_XRGB8888 are always supported and not included in the
++ * array, but all formats added through wl_display_add_shm_format()
++ * will be in the array.
++ *
++ * \sa wl_display_add_shm_format()
++ *
++ * \private
++ *
++ * \memberof wl_display
++ */
++struct wl_array *
++wl_display_get_additional_shm_formats(struct wl_display *display)
++{
++ return &display->additional_shm_formats;
++}
++
++/** Get the list of currently connected clients
++ *
++ * \param display The display object
++ *
++ * This function returns a pointer to the list of clients currently
++ * connected to the display. You can iterate on the list by using
++ * the \a wl_client_for_each macro.
++ * The returned value is valid for the lifetime of the \a display.
++ * You must not modify the returned list, but only access it.
++ *
++ * \sa wl_client_for_each()
++ * \sa wl_client_get_link()
++ * \sa wl_client_from_link()
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT struct wl_list *
++wl_display_get_client_list(struct wl_display *display)
++{
++ return &display->client_list;
++}
++
++/** Get the link by which a client is inserted in the client list
++ *
++ * \param client The client object
++ *
++ * \sa wl_client_for_each()
++ * \sa wl_display_get_client_list()
++ * \sa wl_client_from_link()
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT struct wl_list *
++wl_client_get_link(struct wl_client *client)
++{
++ return &client->link;
++}
++
++/** Get a wl_client by its link
++ *
++ * \param link The link of a wl_client
++ *
++ * \sa wl_client_for_each()
++ * \sa wl_display_get_client_list()
++ * \sa wl_client_get_link()
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT struct wl_client *
++wl_client_from_link(struct wl_list *link)
++{
++ struct wl_client *client;
++
++ return wl_container_of(link, client, link);
++}
++
++/** Add a listener for the client's resource creation signal
++ *
++ * \param client The client object
++ * \param listener The listener to be added
++ *
++ * When a new resource is created for this client the listener
++ * will be notified, carrying the new resource as the data argument.
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT void
++wl_client_add_resource_created_listener(struct wl_client *client,
++ struct wl_listener *listener)
++{
++ wl_priv_signal_add(&client->resource_created_signal, listener);
++}
++
++struct wl_resource_iterator_context {
++ void *user_data;
++ wl_client_for_each_resource_iterator_func_t it;
++};
++
++static enum wl_iterator_result
++resource_iterator_helper(void *res, void *user_data, uint32_t flags)
++{
++ struct wl_resource_iterator_context *context = user_data;
++ struct wl_resource *resource = res;
++
++ return context->it(resource, context->user_data);
++}
++
++/** Iterate over all the resources of a client
++ *
++ * \param client The client object
++ * \param iterator The iterator function
++ * \param user_data The user data pointer
++ *
++ * The function pointed by \a iterator will be called for each
++ * resource owned by the client. The \a user_data will be passed
++ * as the second argument of the iterator function.
++ * If the \a iterator function returns \a WL_ITERATOR_CONTINUE the iteration
++ * will continue, if it returns \a WL_ITERATOR_STOP it will stop.
++ *
++ * Creating and destroying resources while iterating is safe, but new
++ * resources may or may not be picked up by the iterator.
++ *
++ * \sa wl_iterator_result
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT void
++wl_client_for_each_resource(struct wl_client *client,
++ wl_client_for_each_resource_iterator_func_t iterator,
++ void *user_data)
++{
++ struct wl_resource_iterator_context context = {
++ .user_data = user_data,
++ .it = iterator,
++ };
++
++ wl_map_for_each(&client->objects, resource_iterator_helper, &context);
++}
++
++static void
++handle_noop(struct wl_listener *listener, void *data)
++{
++ /* Do nothing */
++}
++
++/** Emits this signal, notifying all registered listeners.
++ *
++ * A safer version of wl_signal_emit() which can gracefully handle additions
++ * and deletions of any signal listener from within listener notification
++ * callbacks.
++ *
++ * Listeners deleted during a signal emission and which have not already been
++ * notified at the time of deletion are not notified by that emission.
++ *
++ * Listeners added (or readded) during signal emission are ignored by that
++ * emission.
++ *
++ * Note that repurposing a listener without explicitly removing it and readding
++ * it is not supported and can lead to unexpected behavior.
++ *
++ * \param signal The signal object that will emit the signal
++ * \param data The data that will be emitted with the signal
++ *
++ * \memberof wl_signal
++ * \since 1.20.90
++ */
++WL_EXPORT void
++wl_signal_emit_mutable(struct wl_signal *signal, void *data)
++{
++ struct wl_listener cursor;
++ struct wl_listener end;
++
++ /* Add two special markers: one cursor and one end marker. This way, we
++ * know that we've already called listeners on the left of the cursor
++ * and that we don't want to call listeners on the right of the end
++ * marker. The 'it' function can remove any element it wants from the
++ * list without troubles.
++ *
++ * There was a previous attempt that used to steal the whole list of
++ * listeners but then that broke wl_signal_get().
++ *
++ * wl_list_for_each_safe tries to be safe but it fails: it works fine
++ * if the current item is removed, but not if the next one is. */
++ wl_list_insert(&signal->listener_list, &cursor.link);
++ cursor.notify = handle_noop;
++ wl_list_insert(signal->listener_list.prev, &end.link);
++ end.notify = handle_noop;
++
++ while (cursor.link.next != &end.link) {
++ struct wl_list *pos = cursor.link.next;
++ struct wl_listener *l = wl_container_of(pos, l, link);
++
++ wl_list_remove(&cursor.link);
++ wl_list_insert(pos, &cursor.link);
++
++ l->notify(l, data);
++ }
++
++ wl_list_remove(&cursor.link);
++ wl_list_remove(&end.link);
++}
++
++/** \cond INTERNAL */
++
++/** Initialize a wl_priv_signal object
++ *
++ * wl_priv_signal is a safer implementation of a signal type, with the same API
++ * as wl_signal, but kept as a private utility of libwayland-server.
++ * It is safer because listeners can be removed from within wl_priv_signal_emit()
++ * without corrupting the signal's list.
++ *
++ * Before passing a wl_priv_signal object to any other function it must be
++ * initialized by using wl_priv_signal_init().
++ *
++ * \memberof wl_priv_signal
++ */
++void
++wl_priv_signal_init(struct wl_priv_signal *signal)
++{
++ wl_list_init(&signal->listener_list);
++ wl_list_init(&signal->emit_list);
++}
++
++/** Add a listener to a signal
++ *
++ * The new listener will be called when calling wl_signal_emit(). If a listener is
++ * added to the signal while wl_signal_emit() is running it will be called from
++ * the next time wl_priv_signal_emit() is called.
++ * To remove a listener call wl_list_remove() on its link member.
++ *
++ * \memberof wl_priv_signal
++ */
++void
++wl_priv_signal_add(struct wl_priv_signal *signal, struct wl_listener *listener)
++{
++ wl_list_insert(signal->listener_list.prev, &listener->link);
++}
++
++/** Get a listener added to a signal
++ *
++ * Returns the listener added to the given \a signal and with the given
++ * \a notify function, or NULL if there isn't any.
++ * Calling this function from within wl_priv_signal_emit() is safe and will
++ * return the correct value.
++ *
++ * \memberof wl_priv_signal
++ */
++struct wl_listener *
++wl_priv_signal_get(struct wl_priv_signal *signal, wl_notify_func_t notify)
++{
++ struct wl_listener *l;
++
++ wl_list_for_each(l, &signal->listener_list, link)
++ if (l->notify == notify)
++ return l;
++ wl_list_for_each(l, &signal->emit_list, link)
++ if (l->notify == notify)
++ return l;
++
++ return NULL;
++}
++
++/** Emit the signal, calling all the installed listeners
++ *
++ * Iterate over all the listeners added to this \a signal and call
++ * their \a notify function pointer, passing on the given \a data.
++ * Removing or adding a listener from within wl_priv_signal_emit()
++ * is safe.
++ */
++void
++wl_priv_signal_emit(struct wl_priv_signal *signal, void *data)
++{
++ struct wl_listener *l;
++ struct wl_list *pos;
++
++ wl_list_insert_list(&signal->emit_list, &signal->listener_list);
++ wl_list_init(&signal->listener_list);
++
++ /* Take every element out of the list and put them in a temporary list.
++ * This way, the 'it' func can remove any element it wants from the list
++ * without troubles, because we always get the first element, not the
++ * one after the current, which may be invalid.
++ * wl_list_for_each_safe tries to be safe but it fails: it works fine
++ * if the current item is removed, but not if the next one is. */
++ while (!wl_list_empty(&signal->emit_list)) {
++ pos = signal->emit_list.next;
++ l = wl_container_of(pos, l, link);
++
++ wl_list_remove(pos);
++ wl_list_insert(&signal->listener_list, pos);
++
++ l->notify(l, data);
++ }
++}
++
++/** Emit the signal for the last time, calling all the installed listeners
++ *
++ * Iterate over all the listeners added to this \a signal and call
++ * their \a notify function pointer, passing on the given \a data.
++ * Removing or adding a listener from within wl_priv_signal_emit()
++ * is safe, as is freeing the structure containing the listener.
++ *
++ * A large body of external code assumes it's ok to free a destruction
++ * listener without removing that listener from the list. Mixing code
++ * that acts like this and code that doesn't will result in list
++ * corruption.
++ *
++ * We resolve this by removing each item from the list and isolating it
++ * in another list. We discard it completely after firing the notifier.
++ * This should allow interoperability between code that unlinks its
++ * destruction listeners and code that just frees structures they're in.
++ *
++ */
++void
++wl_priv_signal_final_emit(struct wl_priv_signal *signal, void *data)
++{
++ struct wl_listener *l;
++ struct wl_list *pos;
++
++ /* During a destructor notifier isolate every list item before
++ * notifying. This renders harmless the long standing misuse
++ * of freeing listeners without removing them, but allows
++ * callers that do choose to remove them to interoperate with
++ * ones that don't. */
++ while (!wl_list_empty(&signal->listener_list)) {
++ pos = signal->listener_list.next;
++ l = wl_container_of(pos, l, link);
++
++ wl_list_remove(pos);
++ wl_list_init(pos);
++
++ l->notify(l, data);
++ }
++}
++
++/** \endcond INTERNAL */
++
++/** \cond */ /* Deprecated functions below. */
++
++uint32_t
++wl_client_add_resource(struct wl_client *client,
++ struct wl_resource *resource) WL_DEPRECATED;
++
++WL_EXPORT uint32_t
++wl_client_add_resource(struct wl_client *client,
++ struct wl_resource *resource)
++{
++ if (resource->object.id == 0) {
++ resource->object.id =
++ wl_map_insert_new(&client->objects,
++ WL_MAP_ENTRY_LEGACY, resource);
++ if (resource->object.id == 0)
++ return 0;
++ } else if (wl_map_insert_at(&client->objects, WL_MAP_ENTRY_LEGACY,
++ resource->object.id, resource) < 0) {
++ if (errno == EINVAL) {
++ wl_resource_post_error(client->display_resource,
++ WL_DISPLAY_ERROR_INVALID_OBJECT,
++ "invalid new id %d",
++ resource->object.id);
++ }
++ return 0;
++ }
++
++ resource->client = client;
++ wl_signal_init(&resource->deprecated_destroy_signal);
++
++ return resource->object.id;
++}
++
++struct wl_resource *
++wl_client_add_object(struct wl_client *client,
++ const struct wl_interface *interface,
++ const void *implementation,
++ uint32_t id, void *data) WL_DEPRECATED;
++
++WL_EXPORT struct wl_resource *
++wl_client_add_object(struct wl_client *client,
++ const struct wl_interface *interface,
++ const void *implementation, uint32_t id, void *data)
++{
++ struct wl_resource *resource;
++
++ resource = wl_resource_create(client, interface, -1, id);
++ if (resource == NULL)
++ wl_client_post_no_memory(client);
++ else
++ wl_resource_set_implementation(resource,
++ implementation, data, NULL);
++
++ return resource;
++}
++
++struct wl_resource *
++wl_client_new_object(struct wl_client *client,
++ const struct wl_interface *interface,
++ const void *implementation, void *data) WL_DEPRECATED;
++
++WL_EXPORT struct wl_resource *
++wl_client_new_object(struct wl_client *client,
++ const struct wl_interface *interface,
++ const void *implementation, void *data)
++{
++ struct wl_resource *resource;
++
++ resource = wl_resource_create(client, interface, -1, 0);
++ if (resource == NULL)
++ wl_client_post_no_memory(client);
++ else
++ wl_resource_set_implementation(resource,
++ implementation, data, NULL);
++
++ return resource;
++}
++
++struct wl_global *
++wl_display_add_global(struct wl_display *display,
++ const struct wl_interface *interface,
++ void *data, wl_global_bind_func_t bind) WL_DEPRECATED;
++
++WL_EXPORT struct wl_global *
++wl_display_add_global(struct wl_display *display,
++ const struct wl_interface *interface,
++ void *data, wl_global_bind_func_t bind)
++{
++ return wl_global_create(display, interface, interface->version, data, bind);
++}
++
++void
++wl_display_remove_global(struct wl_display *display,
++ struct wl_global *global) WL_DEPRECATED;
++
++WL_EXPORT void
++wl_display_remove_global(struct wl_display *display, struct wl_global *global)
++{
++ wl_global_destroy(global);
++}
++
++/** \endcond */
++
++/* Functions at the end of this file are deprecated. Instead of adding new
++ * code here, add it before the comment above that states:
++ * Deprecated functions below.
++ */
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++/** \file
++ *
++ * \brief Include the server API, deprecations and protocol C API.
++ *
++ * \warning Use of this header file is discouraged. Prefer including
++ * wayland-server-core.h instead, which does not include the
++ * server protocol header and as such only defines the library
++ * API, excluding the deprecated API below.
++ */
++
++#ifndef WAYLAND_SERVER_H
++#define WAYLAND_SERVER_H
++
++#include <stdint.h>
++#include "wayland-server-core.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*
++ * The user can set this macro to hide the wl_object, wl_resource and wl_buffer
++ * objects alongside the associated API.
++ *
++ * The structs were meant to be opaque, although we missed that in the early days.
++ *
++ * NOTE: the list of structs, functions, etc in this section MUST NEVER GROW.
++ * Otherwise we will break forward compatibility and applications that used to
++ * build fine will no longer be able to do so.
++ */
++#ifndef WL_HIDE_DEPRECATED
++
++struct wl_object {
++ const struct wl_interface *interface;
++ const void *implementation;
++ uint32_t id;
++};
++
++struct wl_resource {
++ struct wl_object object;
++ wl_resource_destroy_func_t destroy;
++ struct wl_list link;
++ struct wl_signal destroy_signal;
++ struct wl_client *client;
++ void *data;
++};
++
++uint32_t
++wl_client_add_resource(struct wl_client *client,
++ struct wl_resource *resource) WL_DEPRECATED;
++
++struct wl_resource *
++wl_client_add_object(struct wl_client *client,
++ const struct wl_interface *interface,
++ const void *implementation,
++ uint32_t id, void *data) WL_DEPRECATED;
++
++struct wl_resource *
++wl_client_new_object(struct wl_client *client,
++ const struct wl_interface *interface,
++ const void *implementation, void *data) WL_DEPRECATED;
++
++struct wl_global *
++wl_display_add_global(struct wl_display *display,
++ const struct wl_interface *interface,
++ void *data,
++ wl_global_bind_func_t bind) WL_DEPRECATED;
++
++void
++wl_display_remove_global(struct wl_display *display,
++ struct wl_global *global) WL_DEPRECATED;
++
++#endif
++
++#ifdef __cplusplus
++}
++#endif
++
++#include "wayland-server-protocol.h"
++
++#endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ * Authors:
++ * Kristian Høgsberg <krh@bitplanet.net>
++ * Benjamin Franzke <benjaminfranzke@googlemail.com>
++ *
++ */
++
++#define _GNU_SOURCE
++
++#include "config.h"
++
++#include <stdbool.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <string.h>
++#include <sys/mman.h>
++#include <sys/stat.h>
++#include <unistd.h>
++#include <assert.h>
++#include <signal.h>
++#include <pthread.h>
++#include <errno.h>
++#include <fcntl.h>
++
++#include "wayland-os.h"
++#include "wayland-util.h"
++#include "wayland-private.h"
++#include "wayland-server.h"
++
++/* This once_t is used to synchronize installing the SIGBUS handler
++ * and creating the TLS key. This will be done in the first call
++ * wl_shm_buffer_begin_access which can happen from any thread */
++static pthread_once_t wl_shm_sigbus_once = PTHREAD_ONCE_INIT;
++static pthread_key_t wl_shm_sigbus_data_key;
++static struct sigaction wl_shm_old_sigbus_action;
++
++struct wl_shm_pool {
++ struct wl_resource *resource;
++ int internal_refcount;
++ int external_refcount;
++ char *data;
++ ssize_t size;
++ ssize_t new_size;
++#ifndef MREMAP_MAYMOVE
++ /* The following three fields are needed for mremap() emulation. */
++ int mmap_fd;
++ int mmap_flags;
++ int mmap_prot;
++#endif
++ bool sigbus_is_impossible;
++};
++
++/** \class wl_shm_buffer
++ *
++ * \brief A SHM buffer
++ *
++ * wl_shm_buffer provides a helper for accessing the contents of a wl_buffer
++ * resource created via the wl_shm interface.
++ *
++ * A wl_shm_buffer becomes invalid as soon as its #wl_resource is destroyed.
++ */
++struct wl_shm_buffer {
++ struct wl_resource *resource;
++ int32_t width, height;
++ int32_t stride;
++ uint32_t format;
++ int offset;
++ struct wl_shm_pool *pool;
++};
++
++struct wl_shm_sigbus_data {
++ struct wl_shm_pool *current_pool;
++ int access_count;
++ int fallback_mapping_used;
++};
++
++static void *
++shm_pool_grow_mapping(struct wl_shm_pool *pool)
++{
++ void *data;
++
++#ifdef MREMAP_MAYMOVE
++ data = mremap(pool->data, pool->size, pool->new_size, MREMAP_MAYMOVE);
++#else
++ data = wl_os_mremap_maymove(pool->mmap_fd, pool->data, &pool->size,
++ pool->new_size, pool->mmap_prot,
++ pool->mmap_flags);
++ if (pool->size != 0) {
++ wl_resource_post_error(pool->resource,
++ WL_SHM_ERROR_INVALID_FD,
++ "leaked old mapping");
++ }
++#endif
++ return data;
++}
++
++static void
++shm_pool_finish_resize(struct wl_shm_pool *pool)
++{
++ void *data;
++
++ if (pool->size == pool->new_size)
++ return;
++
++ data = shm_pool_grow_mapping(pool);
++ if (data == MAP_FAILED) {
++ wl_resource_post_error(pool->resource,
++ WL_SHM_ERROR_INVALID_FD,
++ "failed mremap");
++ return;
++ }
++
++ pool->data = data;
++ pool->size = pool->new_size;
++}
++
++static void
++shm_pool_unref(struct wl_shm_pool *pool, bool external)
++{
++ if (external) {
++ pool->external_refcount--;
++ assert(pool->external_refcount >= 0);
++ if (pool->external_refcount == 0)
++ shm_pool_finish_resize(pool);
++ } else {
++ pool->internal_refcount--;
++ assert(pool->internal_refcount >= 0);
++ }
++
++ if (pool->internal_refcount + pool->external_refcount > 0)
++ return;
++
++ munmap(pool->data, pool->size);
++#ifndef MREMAP_MAYMOVE
++ close(pool->mmap_fd);
++#endif
++ free(pool);
++}
++
++static void
++destroy_buffer(struct wl_resource *resource)
++{
++ struct wl_shm_buffer *buffer = wl_resource_get_user_data(resource);
++
++ shm_pool_unref(buffer->pool, false);
++ free(buffer);
++}
++
++static void
++shm_buffer_destroy(struct wl_client *client, struct wl_resource *resource)
++{
++ wl_resource_destroy(resource);
++}
++
++static const struct wl_buffer_interface shm_buffer_interface = {
++ shm_buffer_destroy
++};
++
++static bool
++format_is_supported(struct wl_client *client, uint32_t format)
++{
++ struct wl_display *display = wl_client_get_display(client);
++ struct wl_array *formats;
++ uint32_t *p;
++
++ switch (format) {
++ case WL_SHM_FORMAT_ARGB8888:
++ case WL_SHM_FORMAT_XRGB8888:
++ return true;
++ default:
++ formats = wl_display_get_additional_shm_formats(display);
++ wl_array_for_each(p, formats)
++ if (*p == format)
++ return true;
++ }
++
++ return false;
++}
++
++static void
++shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource,
++ uint32_t id, int32_t offset,
++ int32_t width, int32_t height,
++ int32_t stride, uint32_t format)
++{
++ struct wl_shm_pool *pool = wl_resource_get_user_data(resource);
++ struct wl_shm_buffer *buffer;
++
++ if (!format_is_supported(client, format)) {
++ wl_resource_post_error(resource,
++ WL_SHM_ERROR_INVALID_FORMAT,
++ "invalid format 0x%x", format);
++ return;
++ }
++
++ if (offset < 0 || width <= 0 || height <= 0 || stride < width ||
++ INT32_MAX / stride < height ||
++ offset > pool->size - stride * height) {
++ wl_resource_post_error(resource,
++ WL_SHM_ERROR_INVALID_STRIDE,
++ "invalid width, height or stride (%dx%d, %u)",
++ width, height, stride);
++ return;
++ }
++
++ buffer = zalloc(sizeof *buffer);
++ if (buffer == NULL) {
++ wl_client_post_no_memory(client);
++ return;
++ }
++
++ buffer->width = width;
++ buffer->height = height;
++ buffer->format = format;
++ buffer->stride = stride;
++ buffer->offset = offset;
++ buffer->pool = pool;
++ pool->internal_refcount++;
++
++ buffer->resource =
++ wl_resource_create(client, &wl_buffer_interface, 1, id);
++ if (buffer->resource == NULL) {
++ wl_client_post_no_memory(client);
++ shm_pool_unref(pool, false);
++ free(buffer);
++ return;
++ }
++
++ wl_resource_set_implementation(buffer->resource,
++ &shm_buffer_interface,
++ buffer, destroy_buffer);
++}
++
++static void
++destroy_pool(struct wl_resource *resource)
++{
++ struct wl_shm_pool *pool = wl_resource_get_user_data(resource);
++
++ shm_pool_unref(pool, false);
++}
++
++static void
++shm_pool_destroy(struct wl_client *client, struct wl_resource *resource)
++{
++ wl_resource_destroy(resource);
++}
++
++static void
++shm_pool_resize(struct wl_client *client, struct wl_resource *resource,
++ int32_t size)
++{
++ struct wl_shm_pool *pool = wl_resource_get_user_data(resource);
++
++ if (size < pool->size) {
++ wl_resource_post_error(resource,
++ WL_SHM_ERROR_INVALID_FD,
++ "shrinking pool invalid");
++ return;
++ }
++
++ pool->new_size = size;
++
++ /* If the compositor has taken references on this pool it
++ * may be caching pointers into it. In that case we
++ * defer the resize (which may move the entire mapping)
++ * until the compositor finishes dereferencing the pool.
++ */
++ if (pool->external_refcount == 0)
++ shm_pool_finish_resize(pool);
++}
++
++static const struct wl_shm_pool_interface shm_pool_interface = {
++ shm_pool_create_buffer,
++ shm_pool_destroy,
++ shm_pool_resize
++};
++
++static void
++shm_create_pool(struct wl_client *client, struct wl_resource *resource,
++ uint32_t id, int fd, int32_t size)
++{
++ struct wl_shm_pool *pool;
++ struct stat statbuf;
++ int seals;
++ int prot;
++ int flags;
++
++ if (size <= 0) {
++ wl_resource_post_error(resource,
++ WL_SHM_ERROR_INVALID_STRIDE,
++ "invalid size (%d)", size);
++ goto err_close;
++ }
++
++ pool = zalloc(sizeof *pool);
++ if (pool == NULL) {
++ wl_client_post_no_memory(client);
++ goto err_close;
++ }
++
++#ifdef HAVE_MEMFD_CREATE
++ seals = fcntl(fd, F_GET_SEALS);
++ if (seals == -1)
++ seals = 0;
++
++ if ((seals & F_SEAL_SHRINK) && fstat(fd, &statbuf) >= 0)
++ pool->sigbus_is_impossible = statbuf.st_size >= size;
++ else
++ pool->sigbus_is_impossible = false;
++#else
++ pool->sigbus_is_impossible = false;
++#endif
++
++ pool->internal_refcount = 1;
++ pool->external_refcount = 0;
++ pool->size = size;
++ pool->new_size = size;
++ prot = PROT_READ | PROT_WRITE;
++ flags = MAP_SHARED;
++ pool->data = mmap(NULL, size, prot, flags, fd, 0);
++ if (pool->data == MAP_FAILED) {
++ wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FD,
++ "failed mmap fd %d: %s", fd,
++ strerror(errno));
++ goto err_free;
++ }
++#ifndef MREMAP_MAYMOVE
++ /* We may need to keep the fd, prot and flags to emulate mremap(). */
++ pool->mmap_fd = fd;
++ pool->mmap_prot = prot;
++ pool->mmap_flags = flags;
++#else
++ close(fd);
++#endif
++ pool->resource =
++ wl_resource_create(client, &wl_shm_pool_interface, 1, id);
++ if (!pool->resource) {
++ wl_client_post_no_memory(client);
++ munmap(pool->data, pool->size);
++ free(pool);
++ return;
++ }
++
++ wl_resource_set_implementation(pool->resource,
++ &shm_pool_interface,
++ pool, destroy_pool);
++
++ return;
++
++err_free:
++ free(pool);
++err_close:
++ close(fd);
++}
++
++static const struct wl_shm_interface shm_interface = {
++ shm_create_pool
++};
++
++static void
++bind_shm(struct wl_client *client,
++ void *data, uint32_t version, uint32_t id)
++{
++ struct wl_resource *resource;
++ struct wl_display *display = wl_client_get_display(client);
++ struct wl_array *additional_formats;
++ uint32_t *p;
++
++ resource = wl_resource_create(client, &wl_shm_interface, 1, id);
++ if (!resource) {
++ wl_client_post_no_memory(client);
++ return;
++ }
++
++ wl_resource_set_implementation(resource, &shm_interface, data, NULL);
++
++ wl_shm_send_format(resource, WL_SHM_FORMAT_ARGB8888);
++ wl_shm_send_format(resource, WL_SHM_FORMAT_XRGB8888);
++
++ additional_formats = wl_display_get_additional_shm_formats(display);
++ wl_array_for_each(p, additional_formats)
++ wl_shm_send_format(resource, *p);
++}
++
++WL_EXPORT int
++wl_display_init_shm(struct wl_display *display)
++{
++ if (!wl_global_create(display, &wl_shm_interface, 1, NULL, bind_shm))
++ return -1;
++
++ return 0;
++}
++
++WL_EXPORT struct wl_shm_buffer *
++wl_shm_buffer_get(struct wl_resource *resource)
++{
++ if (resource == NULL)
++ return NULL;
++
++ if (wl_resource_instance_of(resource, &wl_buffer_interface,
++ &shm_buffer_interface))
++ return wl_resource_get_user_data(resource);
++ else
++ return NULL;
++}
++
++WL_EXPORT int32_t
++wl_shm_buffer_get_stride(struct wl_shm_buffer *buffer)
++{
++ return buffer->stride;
++}
++
++
++/** Get a pointer to the memory for the SHM buffer
++ *
++ * \param buffer The buffer object
++ *
++ * Returns a pointer which can be used to read the data contained in
++ * the given SHM buffer.
++ *
++ * As this buffer is memory-mapped, reading from it may generate
++ * SIGBUS signals. This can happen if the client claims that the
++ * buffer is larger than it is or if something truncates the
++ * underlying file. To prevent this signal from causing the compositor
++ * to crash you should call wl_shm_buffer_begin_access and
++ * wl_shm_buffer_end_access around code that reads from the memory.
++ *
++ * \memberof wl_shm_buffer
++ */
++WL_EXPORT void *
++wl_shm_buffer_get_data(struct wl_shm_buffer *buffer)
++{
++ if (buffer->pool->external_refcount &&
++ (buffer->pool->size != buffer->pool->new_size))
++ wl_log("Buffer address requested when its parent pool "
++ "has an external reference and a deferred resize "
++ "pending.\n");
++ return buffer->pool->data + buffer->offset;
++}
++
++WL_EXPORT uint32_t
++wl_shm_buffer_get_format(struct wl_shm_buffer *buffer)
++{
++ return buffer->format;
++}
++
++WL_EXPORT int32_t
++wl_shm_buffer_get_width(struct wl_shm_buffer *buffer)
++{
++ return buffer->width;
++}
++
++WL_EXPORT int32_t
++wl_shm_buffer_get_height(struct wl_shm_buffer *buffer)
++{
++ return buffer->height;
++}
++
++/** Get a reference to a shm_buffer's shm_pool
++ *
++ * \param buffer The buffer object
++ *
++ * Returns a pointer to a buffer's shm_pool and increases the
++ * shm_pool refcount.
++ *
++ * The compositor must remember to call wl_shm_pool_unref when
++ * it no longer needs the reference to ensure proper destruction
++ * of the pool.
++ *
++ * \memberof wl_shm_buffer
++ * \sa wl_shm_pool_unref
++ */
++WL_EXPORT struct wl_shm_pool *
++wl_shm_buffer_ref_pool(struct wl_shm_buffer *buffer)
++{
++ assert(buffer->pool->internal_refcount +
++ buffer->pool->external_refcount);
++
++ buffer->pool->external_refcount++;
++ return buffer->pool;
++}
++
++/** Unreference a shm_pool
++ *
++ * \param pool The pool object
++ *
++ * Drops a reference to a wl_shm_pool object.
++ *
++ * This is only necessary if the compositor has explicitly
++ * taken a reference with wl_shm_buffer_ref_pool(), otherwise
++ * the pool will be automatically destroyed when appropriate.
++ *
++ * \memberof wl_shm_pool
++ * \sa wl_shm_buffer_ref_pool
++ */
++WL_EXPORT void
++wl_shm_pool_unref(struct wl_shm_pool *pool)
++{
++ shm_pool_unref(pool, true);
++}
++
++static void
++reraise_sigbus(void)
++{
++ /* If SIGBUS is raised for some other reason than accessing
++ * the pool then we'll uninstall the signal handler so we can
++ * reraise it. This would presumably kill the process */
++ sigaction(SIGBUS, &wl_shm_old_sigbus_action, NULL);
++ raise(SIGBUS);
++}
++
++static void
++sigbus_handler(int signum, siginfo_t *info, void *context)
++{
++ struct wl_shm_sigbus_data *sigbus_data =
++ pthread_getspecific(wl_shm_sigbus_data_key);
++ struct wl_shm_pool *pool;
++
++ if (sigbus_data == NULL) {
++ reraise_sigbus();
++ return;
++ }
++
++ pool = sigbus_data->current_pool;
++
++ /* If the offending address is outside the mapped space for
++ * the pool then the error is a real problem so we'll reraise
++ * the signal */
++ if (pool == NULL ||
++ (char *) info->si_addr < pool->data ||
++ (char *) info->si_addr >= pool->data + pool->size) {
++ reraise_sigbus();
++ return;
++ }
++
++ sigbus_data->fallback_mapping_used = 1;
++
++ /* This should replace the previous mapping */
++ if (mmap(pool->data, pool->size, PROT_READ | PROT_WRITE,
++ MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 0, 0) == MAP_FAILED) {
++ reraise_sigbus();
++ return;
++ }
++}
++
++static void
++destroy_sigbus_data(void *data)
++{
++ struct wl_shm_sigbus_data *sigbus_data = data;
++
++ free(sigbus_data);
++}
++
++static void
++init_sigbus_data_key(void)
++{
++ struct sigaction new_action = {
++ .sa_sigaction = sigbus_handler,
++ .sa_flags = SA_SIGINFO | SA_NODEFER
++ };
++
++ sigemptyset(&new_action.sa_mask);
++
++ sigaction(SIGBUS, &new_action, &wl_shm_old_sigbus_action);
++
++ pthread_key_create(&wl_shm_sigbus_data_key, destroy_sigbus_data);
++}
++
++/** Mark that the given SHM buffer is about to be accessed
++ *
++ * \param buffer The SHM buffer
++ *
++ * An SHM buffer is a memory-mapped file given by the client.
++ * According to POSIX, reading from a memory-mapped region that
++ * extends off the end of the file will cause a SIGBUS signal to be
++ * generated. Normally this would cause the compositor to terminate.
++ * In order to make the compositor robust against clients that change
++ * the size of the underlying file or lie about its size, you should
++ * protect access to the buffer by calling this function before
++ * reading from the memory and call wl_shm_buffer_end_access
++ * afterwards. This will install a signal handler for SIGBUS which
++ * will prevent the compositor from crashing.
++ *
++ * After calling this function the signal handler will remain
++ * installed for the lifetime of the compositor process. Note that
++ * this function will not work properly if the compositor is also
++ * installing its own handler for SIGBUS.
++ *
++ * If a SIGBUS signal is received for an address within the range of
++ * the SHM pool of the given buffer then the client will be sent an
++ * error event when wl_shm_buffer_end_access is called. If the signal
++ * is for an address outside that range then the signal handler will
++ * reraise the signal which would will likely cause the compositor to
++ * terminate.
++ *
++ * It is safe to nest calls to these functions as long as the nested
++ * calls are all accessing the same buffer. The number of calls to
++ * wl_shm_buffer_end_access must match the number of calls to
++ * wl_shm_buffer_begin_access. These functions are thread-safe and it
++ * is allowed to simultaneously access different buffers or the same
++ * buffer from multiple threads.
++ *
++ * \memberof wl_shm_buffer
++ */
++WL_EXPORT void
++wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer)
++{
++ struct wl_shm_pool *pool = buffer->pool;
++ struct wl_shm_sigbus_data *sigbus_data;
++
++ if (pool->sigbus_is_impossible)
++ return;
++
++ pthread_once(&wl_shm_sigbus_once, init_sigbus_data_key);
++
++ sigbus_data = pthread_getspecific(wl_shm_sigbus_data_key);
++ if (sigbus_data == NULL) {
++ sigbus_data = zalloc(sizeof *sigbus_data);
++ if (sigbus_data == NULL)
++ return;
++
++ pthread_setspecific(wl_shm_sigbus_data_key, sigbus_data);
++ }
++
++ assert(sigbus_data->current_pool == NULL ||
++ sigbus_data->current_pool == pool);
++
++ sigbus_data->current_pool = pool;
++ sigbus_data->access_count++;
++}
++
++/** Ends the access to a buffer started by wl_shm_buffer_begin_access
++ *
++ * \param buffer The SHM buffer
++ *
++ * This should be called after wl_shm_buffer_begin_access once the
++ * buffer is no longer being accessed. If a SIGBUS signal was
++ * generated in-between these two calls then the resource for the
++ * given buffer will be sent an error.
++ *
++ * \memberof wl_shm_buffer
++ */
++WL_EXPORT void
++wl_shm_buffer_end_access(struct wl_shm_buffer *buffer)
++{
++ struct wl_shm_pool *pool = buffer->pool;
++ struct wl_shm_sigbus_data *sigbus_data;
++
++ if (pool->sigbus_is_impossible)
++ return;
++
++ sigbus_data = pthread_getspecific(wl_shm_sigbus_data_key);
++ assert(sigbus_data && sigbus_data->access_count >= 1);
++
++ if (--sigbus_data->access_count == 0) {
++ if (sigbus_data->fallback_mapping_used) {
++ wl_resource_post_error(buffer->resource,
++ WL_SHM_ERROR_INVALID_FD,
++ "error accessing SHM buffer");
++ sigbus_data->fallback_mapping_used = 0;
++ }
++
++ sigbus_data->current_pool = NULL;
++ }
++}
++
++/** \cond */ /* Deprecated functions below. */
++
++WL_EXPORT struct wl_shm_buffer *
++wl_shm_buffer_create(struct wl_client *client,
++ uint32_t id, int32_t width, int32_t height,
++ int32_t stride, uint32_t format)
++{
++ return NULL;
++}
++
++/** \endcond */
++
++/* Functions at the end of this file are deprecated. Instead of adding new
++ * code here, add it before the comment above that states:
++ * Deprecated functions below.
++ */
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2011 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <errno.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <string.h>
++#include <stdarg.h>
++
++#include "wayland-util.h"
++#include "wayland-private.h"
++
++WL_EXPORT void
++wl_list_init(struct wl_list *list)
++{
++ list->prev = list;
++ list->next = list;
++}
++
++WL_EXPORT void
++wl_list_insert(struct wl_list *list, struct wl_list *elm)
++{
++ elm->prev = list;
++ elm->next = list->next;
++ list->next = elm;
++ elm->next->prev = elm;
++}
++
++WL_EXPORT void
++wl_list_remove(struct wl_list *elm)
++{
++ elm->prev->next = elm->next;
++ elm->next->prev = elm->prev;
++ elm->next = NULL;
++ elm->prev = NULL;
++}
++
++WL_EXPORT int
++wl_list_length(const struct wl_list *list)
++{
++ struct wl_list *e;
++ int count;
++
++ count = 0;
++ e = list->next;
++ while (e != list) {
++ e = e->next;
++ count++;
++ }
++
++ return count;
++}
++
++WL_EXPORT int
++wl_list_empty(const struct wl_list *list)
++{
++ return list->next == list;
++}
++
++WL_EXPORT void
++wl_list_insert_list(struct wl_list *list, struct wl_list *other)
++{
++ if (wl_list_empty(other))
++ return;
++
++ other->next->prev = list;
++ other->prev->next = list->next;
++ list->next->prev = other->prev;
++ list->next = other->next;
++}
++
++WL_EXPORT void
++wl_array_init(struct wl_array *array)
++{
++ memset(array, 0, sizeof *array);
++}
++
++WL_EXPORT void
++wl_array_release(struct wl_array *array)
++{
++ free(array->data);
++ array->data = WL_ARRAY_POISON_PTR;
++}
++
++WL_EXPORT void *
++wl_array_add(struct wl_array *array, size_t size)
++{
++ size_t alloc;
++ void *data, *p;
++
++ if (array->alloc > 0)
++ alloc = array->alloc;
++ else
++ alloc = 16;
++
++ while (alloc < array->size + size)
++ alloc *= 2;
++
++ if (array->alloc < alloc) {
++ if (array->alloc > 0)
++ data = realloc(array->data, alloc);
++ else
++ data = malloc(alloc);
++
++ if (data == NULL)
++ return NULL;
++ array->data = data;
++ array->alloc = alloc;
++ }
++
++ p = (char *)array->data + array->size;
++ array->size += size;
++
++ return p;
++}
++
++WL_EXPORT int
++wl_array_copy(struct wl_array *array, struct wl_array *source)
++{
++ if (array->size < source->size) {
++ if (!wl_array_add(array, source->size - array->size))
++ return -1;
++ } else {
++ array->size = source->size;
++ }
++
++ if (source->size > 0)
++ memcpy(array->data, source->data, source->size);
++
++ return 0;
++}
++
++/** \cond */
++
++int
++wl_interface_equal(const struct wl_interface *a, const struct wl_interface *b)
++{
++ /* In most cases the pointer equality test is sufficient.
++ * However, in some cases, depending on how things are split
++ * across shared objects, we can end up with multiple
++ * instances of the interface metadata constants. So if the
++ * pointers match, the interfaces are equal, if they don't
++ * match we have to compare the interface names.
++ */
++ return a == b || strcmp(a->name, b->name) == 0;
++}
++
++union map_entry {
++ uintptr_t next;
++ void *data;
++};
++
++#define map_entry_is_free(entry) ((entry).next & 0x1)
++#define map_entry_get_data(entry) ((void *)((entry).next & ~(uintptr_t)0x3))
++#define map_entry_get_flags(entry) (((entry).next >> 1) & 0x1)
++
++void
++wl_map_init(struct wl_map *map, uint32_t side)
++{
++ memset(map, 0, sizeof *map);
++ map->side = side;
++}
++
++void
++wl_map_release(struct wl_map *map)
++{
++ wl_array_release(&map->client_entries);
++ wl_array_release(&map->server_entries);
++}
++
++uint32_t
++wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data)
++{
++ union map_entry *start, *entry;
++ struct wl_array *entries;
++ uint32_t base;
++ uint32_t count;
++
++ if (map->side == WL_MAP_CLIENT_SIDE) {
++ entries = &map->client_entries;
++ base = 0;
++ } else {
++ entries = &map->server_entries;
++ base = WL_SERVER_ID_START;
++ }
++
++ if (map->free_list) {
++ start = entries->data;
++ entry = &start[map->free_list >> 1];
++ map->free_list = entry->next;
++ } else {
++ entry = wl_array_add(entries, sizeof *entry);
++ if (!entry)
++ return 0;
++ start = entries->data;
++ }
++
++ /* wl_array only grows, so if we have too many objects at
++ * this point there's no way to clean up. We could be more
++ * pro-active about trying to avoid this allocation, but
++ * it doesn't really matter because at this point there is
++ * nothing to be done but disconnect the client and delete
++ * the whole array either way.
++ */
++ count = entry - start;
++ if (count > WL_MAP_MAX_OBJECTS) {
++ /* entry->data is freshly malloced garbage, so we'd
++ * better make it a NULL so wl_map_for_each doesn't
++ * dereference it later. */
++ entry->data = NULL;
++ errno = ENOSPC;
++ return 0;
++ }
++ entry->data = data;
++ entry->next |= (flags & 0x1) << 1;
++
++ return count + base;
++}
++
++int
++wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void *data)
++{
++ union map_entry *start;
++ uint32_t count;
++ struct wl_array *entries;
++
++ if (i < WL_SERVER_ID_START) {
++ entries = &map->client_entries;
++ } else {
++ entries = &map->server_entries;
++ i -= WL_SERVER_ID_START;
++ }
++
++ if (i > WL_MAP_MAX_OBJECTS) {
++ errno = ENOSPC;
++ return -1;
++ }
++
++ count = entries->size / sizeof *start;
++ if (count < i) {
++ errno = EINVAL;
++ return -1;
++ }
++
++ if (count == i) {
++ if (!wl_array_add(entries, sizeof *start))
++ return -1;
++ }
++
++ start = entries->data;
++ start[i].data = data;
++ start[i].next |= (flags & 0x1) << 1;
++
++ return 0;
++}
++
++int
++wl_map_reserve_new(struct wl_map *map, uint32_t i)
++{
++ union map_entry *start;
++ uint32_t count;
++ struct wl_array *entries;
++
++ if (i < WL_SERVER_ID_START) {
++ if (map->side == WL_MAP_CLIENT_SIDE) {
++ errno = EINVAL;
++ return -1;
++ }
++
++ entries = &map->client_entries;
++ } else {
++ if (map->side == WL_MAP_SERVER_SIDE) {
++ errno = EINVAL;
++ return -1;
++ }
++
++ entries = &map->server_entries;
++ i -= WL_SERVER_ID_START;
++ }
++
++ if (i > WL_MAP_MAX_OBJECTS) {
++ errno = ENOSPC;
++ return -1;
++ }
++
++ count = entries->size / sizeof *start;
++ if (count < i) {
++ errno = EINVAL;
++ return -1;
++ }
++
++ if (count == i) {
++ if (!wl_array_add(entries, sizeof *start))
++ return -1;
++
++ start = entries->data;
++ start[i].data = NULL;
++ } else {
++ start = entries->data;
++ if (start[i].data != NULL) {
++ errno = EINVAL;
++ return -1;
++ }
++ }
++
++ return 0;
++}
++
++void
++wl_map_remove(struct wl_map *map, uint32_t i)
++{
++ union map_entry *start;
++ struct wl_array *entries;
++
++ if (i < WL_SERVER_ID_START) {
++ if (map->side == WL_MAP_SERVER_SIDE)
++ return;
++
++ entries = &map->client_entries;
++ } else {
++ if (map->side == WL_MAP_CLIENT_SIDE)
++ return;
++
++ entries = &map->server_entries;
++ i -= WL_SERVER_ID_START;
++ }
++
++ start = entries->data;
++ start[i].next = map->free_list;
++ map->free_list = (i << 1) | 1;
++}
++
++void *
++wl_map_lookup(struct wl_map *map, uint32_t i)
++{
++ union map_entry *start;
++ uint32_t count;
++ struct wl_array *entries;
++
++ if (i < WL_SERVER_ID_START) {
++ entries = &map->client_entries;
++ } else {
++ entries = &map->server_entries;
++ i -= WL_SERVER_ID_START;
++ }
++
++ start = entries->data;
++ count = entries->size / sizeof *start;
++
++ if (i < count && !map_entry_is_free(start[i]))
++ return map_entry_get_data(start[i]);
++
++ return NULL;
++}
++
++uint32_t
++wl_map_lookup_flags(struct wl_map *map, uint32_t i)
++{
++ union map_entry *start;
++ uint32_t count;
++ struct wl_array *entries;
++
++ if (i < WL_SERVER_ID_START) {
++ entries = &map->client_entries;
++ } else {
++ entries = &map->server_entries;
++ i -= WL_SERVER_ID_START;
++ }
++
++ start = entries->data;
++ count = entries->size / sizeof *start;
++
++ if (i < count && !map_entry_is_free(start[i]))
++ return map_entry_get_flags(start[i]);
++
++ return 0;
++}
++
++static enum wl_iterator_result
++for_each_helper(struct wl_array *entries, wl_iterator_func_t func, void *data)
++{
++ enum wl_iterator_result ret = WL_ITERATOR_CONTINUE;
++ union map_entry entry, *start;
++ size_t count;
++
++ start = (union map_entry *) entries->data;
++ count = entries->size / sizeof(union map_entry);
++
++ for (size_t idx = 0; idx < count; idx++) {
++ entry = start[idx];
++ if (entry.data && !map_entry_is_free(entry)) {
++ ret = func(map_entry_get_data(entry), data, map_entry_get_flags(entry));
++ if (ret != WL_ITERATOR_CONTINUE)
++ break;
++ }
++ }
++
++ return ret;
++}
++
++void
++wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data)
++{
++ enum wl_iterator_result ret;
++
++ ret = for_each_helper(&map->client_entries, func, data);
++ if (ret == WL_ITERATOR_CONTINUE)
++ for_each_helper(&map->server_entries, func, data);
++}
++
++static void
++wl_log_stderr_handler(const char *fmt, va_list arg)
++{
++ vfprintf(stderr, fmt, arg);
++}
++
++wl_log_func_t wl_log_handler = wl_log_stderr_handler;
++
++void
++wl_log(const char *fmt, ...)
++{
++ va_list argp;
++
++ va_start(argp, fmt);
++ wl_log_handler(fmt, argp);
++ va_end(argp);
++}
++
++void
++wl_abort(const char *fmt, ...)
++{
++ va_list argp;
++
++ va_start(argp, fmt);
++ wl_log_handler(fmt, argp);
++ va_end(argp);
++
++ abort();
++}
++
++/** \endcond */
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++/** \file wayland-util.h
++ *
++ * \brief Utility classes, functions, and macros.
++ */
++
++#ifndef WAYLAND_UTIL_H
++#define WAYLAND_UTIL_H
++
++#include <math.h>
++#include <stddef.h>
++#include <inttypes.h>
++#include <stdarg.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/** Visibility attribute */
++#if defined(__GNUC__) && __GNUC__ >= 4
++#define WL_EXPORT __attribute__ ((visibility("default")))
++#else
++#define WL_EXPORT
++#endif
++
++/** Deprecated attribute */
++#if defined(__GNUC__) && __GNUC__ >= 4
++#define WL_DEPRECATED __attribute__ ((deprecated))
++#else
++#define WL_DEPRECATED
++#endif
++
++/**
++ * Printf-style argument attribute
++ *
++ * \param x Ordinality of the format string argument
++ * \param y Ordinality of the argument to check against the format string
++ *
++ * \sa https://gcc.gnu.org/onlinedocs/gcc-3.2.1/gcc/Function-Attributes.html
++ */
++#if defined(__GNUC__) && __GNUC__ >= 4
++#define WL_PRINTF(x, y) __attribute__((__format__(__printf__, x, y)))
++#else
++#define WL_PRINTF(x, y)
++#endif
++
++/** \class wl_object
++ *
++ * \brief A protocol object.
++ *
++ * A `wl_object` is an opaque struct identifying the protocol object
++ * underlying a `wl_proxy` or `wl_resource`.
++ *
++ * \note Functions accessing a `wl_object` are not normally used by client code.
++ * Clients should normally use the higher level interface generated by the
++ * scanner to interact with compositor objects.
++ *
++ */
++struct wl_object;
++
++/**
++ * Protocol message signature
++ *
++ * A wl_message describes the signature of an actual protocol message, such as a
++ * request or event, that adheres to the Wayland protocol wire format. The
++ * protocol implementation uses a wl_message within its demarshal machinery for
++ * decoding messages between a compositor and its clients. In a sense, a
++ * wl_message is to a protocol message like a class is to an object.
++ *
++ * The `name` of a wl_message is the name of the corresponding protocol message.
++ *
++ * The `signature` is an ordered list of symbols representing the data types
++ * of message arguments and, optionally, a protocol version and indicators for
++ * nullability. A leading integer in the `signature` indicates the _since_
++ * version of the protocol message. A `?` preceding a data type symbol indicates
++ * that the following argument type is nullable. While it is a protocol violation
++ * to send messages with non-nullable arguments set to `NULL`, event handlers in
++ * clients might still get called with non-nullable object arguments set to
++ * `NULL`. This can happen when the client destroyed the object being used as
++ * argument on its side and an event referencing that object was sent before the
++ * server knew about its destruction. As this race cannot be prevented, clients
++ * should - as a general rule - program their event handlers such that they can
++ * handle object arguments declared non-nullable being `NULL` gracefully.
++ *
++ * When no arguments accompany a message, `signature` is an empty string.
++ *
++ * Symbols:
++ *
++ * * `i`: int
++ * * `u`: uint
++ * * `f`: fixed
++ * * `s`: string
++ * * `o`: object
++ * * `n`: new_id
++ * * `a`: array
++ * * `h`: fd
++ * * `?`: following argument (`o` or `s`) is nullable
++ *
++ * While demarshaling primitive arguments is straightforward, when demarshaling
++ * messages containing `object` or `new_id` arguments, the protocol
++ * implementation often must determine the type of the object. The `types` of a
++ * wl_message is an array of wl_interface references that correspond to `o` and
++ * `n` arguments in `signature`, with `NULL` placeholders for arguments with
++ * non-object types.
++ *
++ * Consider the protocol event wl_display `delete_id` that has a single `uint`
++ * argument. The wl_message is:
++ *
++ * \code
++ * { "delete_id", "u", [NULL] }
++ * \endcode
++ *
++ * Here, the message `name` is `"delete_id"`, the `signature` is `"u"`, and the
++ * argument `types` is `[NULL]`, indicating that the `uint` argument has no
++ * corresponding wl_interface since it is a primitive argument.
++ *
++ * In contrast, consider a `wl_foo` interface supporting protocol request `bar`
++ * that has existed since version 2, and has two arguments: a `uint` and an
++ * object of type `wl_baz_interface` that may be `NULL`. Such a `wl_message`
++ * might be:
++ *
++ * \code
++ * { "bar", "2u?o", [NULL, &wl_baz_interface] }
++ * \endcode
++ *
++ * Here, the message `name` is `"bar"`, and the `signature` is `"2u?o"`. Notice
++ * how the `2` indicates the protocol version, the `u` indicates the first
++ * argument type is `uint`, and the `?o` indicates that the second argument
++ * is an object that may be `NULL`. Lastly, the argument `types` array indicates
++ * that no wl_interface corresponds to the first argument, while the type
++ * `wl_baz_interface` corresponds to the second argument.
++ *
++ * \sa wl_argument
++ * \sa wl_interface
++ * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Wire-Format">Wire Format</a>
++ */
++struct wl_message {
++ /** Message name */
++ const char *name;
++ /** Message signature */
++ const char *signature;
++ /** Object argument interfaces */
++ const struct wl_interface **types;
++};
++
++/**
++ * Protocol object interface
++ *
++ * A wl_interface describes the API of a protocol object defined in the Wayland
++ * protocol specification. The protocol implementation uses a wl_interface
++ * within its marshalling machinery for encoding client requests.
++ *
++ * The `name` of a wl_interface is the name of the corresponding protocol
++ * interface, and `version` represents the version of the interface. The members
++ * `method_count` and `event_count` represent the number of `methods` (requests)
++ * and `events` in the respective wl_message members.
++ *
++ * For example, consider a protocol interface `foo`, marked as version `1`, with
++ * two requests and one event.
++ *
++ * \code{.xml}
++ * <interface name="foo" version="1">
++ * <request name="a"></request>
++ * <request name="b"></request>
++ * <event name="c"></event>
++ * </interface>
++ * \endcode
++ *
++ * Given two wl_message arrays `foo_requests` and `foo_events`, a wl_interface
++ * for `foo` might be:
++ *
++ * \code
++ * struct wl_interface foo_interface = {
++ * "foo", 1,
++ * 2, foo_requests,
++ * 1, foo_events
++ * };
++ * \endcode
++ *
++ * \note The server side of the protocol may define interface <em>implementation
++ * types</em> that incorporate the term `interface` in their name. Take
++ * care to not confuse these server-side `struct`s with a wl_interface
++ * variable whose name also ends in `interface`. For example, while the
++ * server may define a type `struct wl_foo_interface`, the client may
++ * define a `struct wl_interface wl_foo_interface`.
++ *
++ * \sa wl_message
++ * \sa wl_proxy
++ * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Interfaces">Interfaces</a>
++ * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Versioning">Versioning</a>
++ */
++struct wl_interface {
++ /** Interface name */
++ const char *name;
++ /** Interface version */
++ int version;
++ /** Number of methods (requests) */
++ int method_count;
++ /** Method (request) signatures */
++ const struct wl_message *methods;
++ /** Number of events */
++ int event_count;
++ /** Event signatures */
++ const struct wl_message *events;
++};
++
++/** \class wl_list
++ *
++ * \brief Doubly-linked list
++ *
++ * On its own, an instance of `struct wl_list` represents the sentinel head of
++ * a doubly-linked list, and must be initialized using wl_list_init().
++ * When empty, the list head's `next` and `prev` members point to the list head
++ * itself, otherwise `next` references the first element in the list, and `prev`
++ * refers to the last element in the list.
++ *
++ * Use the `struct wl_list` type to represent both the list head and the links
++ * between elements within the list. Use wl_list_empty() to determine if the
++ * list is empty in O(1).
++ *
++ * All elements in the list must be of the same type. The element type must have
++ * a `struct wl_list` member, often named `link` by convention. Prior to
++ * insertion, there is no need to initialize an element's `link` - invoking
++ * wl_list_init() on an individual list element's `struct wl_list` member is
++ * unnecessary if the very next operation is wl_list_insert(). However, a
++ * common idiom is to initialize an element's `link` prior to removal - ensure
++ * safety by invoking wl_list_init() before wl_list_remove().
++ *
++ * Consider a list reference `struct wl_list foo_list`, an element type as
++ * `struct element`, and an element's link member as `struct wl_list link`.
++ *
++ * The following code initializes a list and adds three elements to it.
++ *
++ * \code
++ * struct wl_list foo_list;
++ *
++ * struct element {
++ * int foo;
++ * struct wl_list link;
++ * };
++ * struct element e1, e2, e3;
++ *
++ * wl_list_init(&foo_list);
++ * wl_list_insert(&foo_list, &e1.link); // e1 is the first element
++ * wl_list_insert(&foo_list, &e2.link); // e2 is now the first element
++ * wl_list_insert(&e2.link, &e3.link); // insert e3 after e2
++ * \endcode
++ *
++ * The list now looks like <em>[e2, e3, e1]</em>.
++ *
++ * The `wl_list` API provides some iterator macros. For example, to iterate
++ * a list in ascending order:
++ *
++ * \code
++ * struct element *e;
++ * wl_list_for_each(e, foo_list, link) {
++ * do_something_with_element(e);
++ * }
++ * \endcode
++ *
++ * See the documentation of each iterator for details.
++ * \sa http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/list.h
++ */
++struct wl_list {
++ /** Previous list element */
++ struct wl_list *prev;
++ /** Next list element */
++ struct wl_list *next;
++};
++
++/**
++ * Initializes the list.
++ *
++ * \param list List to initialize
++ *
++ * \memberof wl_list
++ */
++void
++wl_list_init(struct wl_list *list);
++
++/**
++ * Inserts an element into the list, after the element represented by \p list.
++ * When \p list is a reference to the list itself (the head), set the containing
++ * struct of \p elm as the first element in the list.
++ *
++ * \note If \p elm is already part of a list, inserting it again will lead to
++ * list corruption.
++ *
++ * \param list List element after which the new element is inserted
++ * \param elm Link of the containing struct to insert into the list
++ *
++ * \memberof wl_list
++ */
++void
++wl_list_insert(struct wl_list *list, struct wl_list *elm);
++
++/**
++ * Removes an element from the list.
++ *
++ * \note This operation leaves \p elm in an invalid state.
++ *
++ * \param elm Link of the containing struct to remove from the list
++ *
++ * \memberof wl_list
++ */
++void
++wl_list_remove(struct wl_list *elm);
++
++/**
++ * Determines the length of the list.
++ *
++ * \note This is an O(n) operation.
++ *
++ * \param list List whose length is to be determined
++ *
++ * \return Number of elements in the list
++ *
++ * \memberof wl_list
++ */
++int
++wl_list_length(const struct wl_list *list);
++
++/**
++ * Determines if the list is empty.
++ *
++ * \param list List whose emptiness is to be determined
++ *
++ * \return 1 if empty, or 0 if not empty
++ *
++ * \memberof wl_list
++ */
++int
++wl_list_empty(const struct wl_list *list);
++
++/**
++ * Inserts all of the elements of one list into another, after the element
++ * represented by \p list.
++ *
++ * \note This leaves \p other in an invalid state.
++ *
++ * \param list List element after which the other list elements will be inserted
++ * \param other List of elements to insert
++ *
++ * \memberof wl_list
++ */
++void
++wl_list_insert_list(struct wl_list *list, struct wl_list *other);
++
++/**
++ * Retrieves a pointer to a containing struct, given a member name.
++ *
++ * This macro allows "conversion" from a pointer to a member to its containing
++ * struct. This is useful if you have a contained item like a wl_list,
++ * wl_listener, or wl_signal, provided via a callback or other means, and would
++ * like to retrieve the struct that contains it.
++ *
++ * To demonstrate, the following example retrieves a pointer to
++ * `example_container` given only its `destroy_listener` member:
++ *
++ * \code
++ * struct example_container {
++ * struct wl_listener destroy_listener;
++ * // other members...
++ * };
++ *
++ * void example_container_destroy(struct wl_listener *listener, void *data)
++ * {
++ * struct example_container *ctr;
++ *
++ * ctr = wl_container_of(listener, ctr, destroy_listener);
++ * // destroy ctr...
++ * }
++ * \endcode
++ *
++ * \note `sample` need not be a valid pointer. A null or uninitialised pointer
++ * is sufficient.
++ *
++ * \param ptr Valid pointer to the contained member
++ * \param sample Pointer to a struct whose type contains \p ptr
++ * \param member Named location of \p ptr within the \p sample type
++ *
++ * \return The container for the specified pointer
++ */
++#define wl_container_of(ptr, sample, member) \
++ (__typeof__(sample))((char *)(ptr) - \
++ offsetof(__typeof__(*sample), member))
++
++/**
++ * Iterates over a list.
++ *
++ * This macro expresses a for-each iterator for wl_list. Given a list and
++ * wl_list link member name (often named `link` by convention), this macro
++ * assigns each element in the list to \p pos, which can then be referenced in
++ * a trailing code block. For example, given a wl_list of `struct message`
++ * elements:
++ *
++ * \code
++ * struct message {
++ * char *contents;
++ * wl_list link;
++ * };
++ *
++ * struct wl_list *message_list;
++ * // Assume message_list now "contains" many messages
++ *
++ * struct message *m;
++ * wl_list_for_each(m, message_list, link) {
++ * do_something_with_message(m);
++ * }
++ * \endcode
++ *
++ * \param pos Cursor that each list element will be assigned to
++ * \param head Head of the list to iterate over
++ * \param member Name of the link member within the element struct
++ *
++ * \relates wl_list
++ */
++#define wl_list_for_each(pos, head, member) \
++ for (pos = wl_container_of((head)->next, pos, member); \
++ &pos->member != (head); \
++ pos = wl_container_of(pos->member.next, pos, member))
++
++/**
++ * Iterates over a list, safe against removal of the list element.
++ *
++ * \note Only removal of the current element, \p pos, is safe. Removing
++ * any other element during traversal may lead to a loop malfunction.
++ *
++ * \sa wl_list_for_each()
++ *
++ * \param pos Cursor that each list element will be assigned to
++ * \param tmp Temporary pointer of the same type as \p pos
++ * \param head Head of the list to iterate over
++ * \param member Name of the link member within the element struct
++ *
++ * \relates wl_list
++ */
++#define wl_list_for_each_safe(pos, tmp, head, member) \
++ for (pos = wl_container_of((head)->next, pos, member), \
++ tmp = wl_container_of((pos)->member.next, tmp, member); \
++ &pos->member != (head); \
++ pos = tmp, \
++ tmp = wl_container_of(pos->member.next, tmp, member))
++
++/**
++ * Iterates backwards over a list.
++ *
++ * \sa wl_list_for_each()
++ *
++ * \param pos Cursor that each list element will be assigned to
++ * \param head Head of the list to iterate over
++ * \param member Name of the link member within the element struct
++ *
++ * \relates wl_list
++ */
++#define wl_list_for_each_reverse(pos, head, member) \
++ for (pos = wl_container_of((head)->prev, pos, member); \
++ &pos->member != (head); \
++ pos = wl_container_of(pos->member.prev, pos, member))
++
++/**
++ * Iterates backwards over a list, safe against removal of the list element.
++ *
++ * \note Only removal of the current element, \p pos, is safe. Removing
++ * any other element during traversal may lead to a loop malfunction.
++ *
++ * \sa wl_list_for_each()
++ *
++ * \param pos Cursor that each list element will be assigned to
++ * \param tmp Temporary pointer of the same type as \p pos
++ * \param head Head of the list to iterate over
++ * \param member Name of the link member within the element struct
++ *
++ * \relates wl_list
++ */
++#define wl_list_for_each_reverse_safe(pos, tmp, head, member) \
++ for (pos = wl_container_of((head)->prev, pos, member), \
++ tmp = wl_container_of((pos)->member.prev, tmp, member); \
++ &pos->member != (head); \
++ pos = tmp, \
++ tmp = wl_container_of(pos->member.prev, tmp, member))
++
++/**
++ * \class wl_array
++ *
++ * Dynamic array
++ *
++ * A wl_array is a dynamic array that can only grow until released. It is
++ * intended for relatively small allocations whose size is variable or not known
++ * in advance. While construction of a wl_array does not require all elements to
++ * be of the same size, wl_array_for_each() does require all elements to have
++ * the same type and size.
++ *
++ */
++struct wl_array {
++ /** Array size */
++ size_t size;
++ /** Allocated space */
++ size_t alloc;
++ /** Array data */
++ void *data;
++};
++
++/**
++ * Initializes the array.
++ *
++ * \param array Array to initialize
++ *
++ * \memberof wl_array
++ */
++void
++wl_array_init(struct wl_array *array);
++
++/**
++ * Releases the array data.
++ *
++ * \note Leaves the array in an invalid state.
++ *
++ * \param array Array whose data is to be released
++ *
++ * \memberof wl_array
++ */
++void
++wl_array_release(struct wl_array *array);
++
++/**
++ * Increases the size of the array by \p size bytes.
++ *
++ * \param array Array whose size is to be increased
++ * \param size Number of bytes to increase the size of the array by
++ *
++ * \return A pointer to the beginning of the newly appended space, or NULL when
++ * resizing fails.
++ *
++ * \memberof wl_array
++ */
++void *
++wl_array_add(struct wl_array *array, size_t size);
++
++/**
++ * Copies the contents of \p source to \p array.
++ *
++ * \param array Destination array to copy to
++ * \param source Source array to copy from
++ *
++ * \return 0 on success, or -1 on failure
++ *
++ * \memberof wl_array
++ */
++int
++wl_array_copy(struct wl_array *array, struct wl_array *source);
++
++/**
++ * Iterates over an array.
++ *
++ * This macro expresses a for-each iterator for wl_array. It assigns each
++ * element in the array to \p pos, which can then be referenced in a trailing
++ * code block. \p pos must be a pointer to the array element type, and all
++ * array elements must be of the same type and size.
++ *
++ * \param pos Cursor that each array element will be assigned to
++ * \param array Array to iterate over
++ *
++ * \relates wl_array
++ * \sa wl_list_for_each()
++ */
++#define wl_array_for_each(pos, array) \
++ for (pos = (array)->data; \
++ (const char *) pos < ((const char *) (array)->data + (array)->size); \
++ (pos)++)
++
++/**
++ * Fixed-point number
++ *
++ * A `wl_fixed_t` is a 24.8 signed fixed-point number with a sign bit, 23 bits
++ * of integer precision and 8 bits of decimal precision. Consider `wl_fixed_t`
++ * as an opaque struct with methods that facilitate conversion to and from
++ * `double` and `int` types.
++ */
++typedef int32_t wl_fixed_t;
++
++/**
++ * Converts a fixed-point number to a floating-point number.
++ *
++ * \param f Fixed-point number to convert
++ *
++ * \return Floating-point representation of the fixed-point argument
++ */
++static inline double
++wl_fixed_to_double(wl_fixed_t f)
++{
++ union {
++ double d;
++ int64_t i;
++ } u;
++
++ u.i = ((1023LL + 44LL) << 52) + (1LL << 51) + f;
++
++ return u.d - (3LL << 43);
++}
++
++/**
++ * Converts a floating-point number to a fixed-point number.
++ *
++ * \param d Floating-point number to convert
++ *
++ * \return Fixed-point representation of the floating-point argument
++ */
++static inline wl_fixed_t
++wl_fixed_from_double(double d)
++{
++ union {
++ double d;
++ int64_t i;
++ } u;
++
++ u.d = d + (3LL << (51 - 8));
++
++ return (wl_fixed_t)u.i;
++}
++
++/**
++ * Converts a fixed-point number to an integer.
++ *
++ * \param f Fixed-point number to convert
++ *
++ * \return Integer component of the fixed-point argument
++ */
++static inline int
++wl_fixed_to_int(wl_fixed_t f)
++{
++ return f / 256;
++}
++
++/**
++ * Converts an integer to a fixed-point number.
++ *
++ * \param i Integer to convert
++ *
++ * \return Fixed-point representation of the integer argument
++ */
++static inline wl_fixed_t
++wl_fixed_from_int(int i)
++{
++ return i * 256;
++}
++
++/**
++ * Protocol message argument data types
++ *
++ * This union represents all of the argument types in the Wayland protocol wire
++ * format. The protocol implementation uses wl_argument within its marshalling
++ * machinery for dispatching messages between a client and a compositor.
++ *
++ * \sa wl_message
++ * \sa wl_interface
++ * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-wire-Format">Wire Format</a>
++ */
++union wl_argument {
++ int32_t i; /**< `int` */
++ uint32_t u; /**< `uint` */
++ wl_fixed_t f; /**< `fixed` */
++ const char *s; /**< `string` */
++ struct wl_object *o; /**< `object` */
++ uint32_t n; /**< `new_id` */
++ struct wl_array *a; /**< `array` */
++ int32_t h; /**< `fd` */
++};
++
++/**
++ * Dispatcher function type alias
++ *
++ * A dispatcher is a function that handles the emitting of callbacks in client
++ * code. For programs directly using the C library, this is done by using
++ * libffi to call function pointers. When binding to languages other than C,
++ * dispatchers provide a way to abstract the function calling process to be
++ * friendlier to other function calling systems.
++ *
++ * A dispatcher takes five arguments: The first is the dispatcher-specific
++ * implementation associated with the target object. The second is the object
++ * upon which the callback is being invoked (either wl_proxy or wl_resource).
++ * The third and fourth arguments are the opcode and the wl_message
++ * corresponding to the callback. The final argument is an array of arguments
++ * received from the other process via the wire protocol.
++ *
++ * \param "const void *" Dispatcher-specific implementation data
++ * \param "void *" Callback invocation target (wl_proxy or `wl_resource`)
++ * \param uint32_t Callback opcode
++ * \param "const struct wl_message *" Callback message signature
++ * \param "union wl_argument *" Array of received arguments
++ *
++ * \return 0 on success, or -1 on failure
++ */
++typedef int (*wl_dispatcher_func_t)(const void *, void *, uint32_t,
++ const struct wl_message *,
++ union wl_argument *);
++
++/**
++ * Log function type alias
++ *
++ * The C implementation of the Wayland protocol abstracts the details of
++ * logging. Users may customize the logging behavior, with a function conforming
++ * to the `wl_log_func_t` type, via `wl_log_set_handler_client` and
++ * `wl_log_set_handler_server`.
++ *
++ * A `wl_log_func_t` must conform to the expectations of `vprintf`, and
++ * expects two arguments: a string to write and a corresponding variable
++ * argument list. While the string to write may contain format specifiers and
++ * use values in the variable argument list, the behavior of any `wl_log_func_t`
++ * depends on the implementation.
++ *
++ * \note Take care to not confuse this with `wl_protocol_logger_func_t`, which
++ * is a specific server-side logger for requests and events.
++ *
++ * \param "const char *" String to write to the log, containing optional format
++ * specifiers
++ * \param "va_list" Variable argument list
++ *
++ * \sa wl_log_set_handler_client
++ * \sa wl_log_set_handler_server
++ */
++typedef void (*wl_log_func_t)(const char *, va_list) WL_PRINTF(1, 0);
++
++/**
++ * Return value of an iterator function
++ *
++ * \sa wl_client_for_each_resource_iterator_func_t
++ * \sa wl_client_for_each_resource
++ */
++enum wl_iterator_result {
++ /** Stop the iteration */
++ WL_ITERATOR_STOP,
++ /** Continue the iteration */
++ WL_ITERATOR_CONTINUE
++};
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_VERSION_H
++#define WAYLAND_VERSION_H
++
++#define WAYLAND_VERSION_MAJOR @WAYLAND_VERSION_MAJOR@
++#define WAYLAND_VERSION_MINOR @WAYLAND_VERSION_MINOR@
++#define WAYLAND_VERSION_MICRO @WAYLAND_VERSION_MICRO@
++#define WAYLAND_VERSION "@WAYLAND_VERSION@"
++
++#endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <assert.h>
++#include <string.h>
++#include "wayland-util.h"
++#include "wayland-private.h"
++#include "test-runner.h"
++
++TEST(array_init)
++{
++ struct wl_array array;
++
++ /* fill with garbage to emulate uninitialized memory */
++ memset(&array, 0x57, sizeof array);
++
++ wl_array_init(&array);
++ assert(array.size == 0);
++ assert(array.alloc == 0);
++ assert(array.data == 0);
++}
++
++TEST(array_release)
++{
++ struct wl_array array;
++ void *ptr;
++
++ wl_array_init(&array);
++ ptr = wl_array_add(&array, 1);
++ assert(ptr != NULL);
++ assert(array.data != NULL);
++
++ wl_array_release(&array);
++ assert(array.data == WL_ARRAY_POISON_PTR);
++}
++
++TEST(array_add)
++{
++ struct mydata {
++ unsigned int a;
++ unsigned int b;
++ double c;
++ double d;
++ };
++
++ const unsigned int iterations = 1321; /* this is arbitrary */
++ const int datasize = sizeof(struct mydata);
++ struct wl_array array;
++ size_t i;
++
++ wl_array_init(&array);
++
++ /* add some data */
++ for (i = 0; i < iterations; i++) {
++ struct mydata* ptr = wl_array_add(&array, datasize);
++ assert(ptr);
++ assert((i + 1) * datasize == array.size);
++
++ ptr->a = i * 3;
++ ptr->b = 20000 - i;
++ ptr->c = (double)(i);
++ ptr->d = (double)(i / 2.);
++ }
++
++ /* verify the data */
++ for (i = 0; i < iterations; ++i) {
++ struct mydata* check = (struct mydata*)array.data + i;
++
++ assert(check->a == i * 3);
++ assert(check->b == 20000 - i);
++ assert(check->c == (double)(i));
++ assert(check->d == (double)(i/2.));
++ }
++
++ wl_array_release(&array);
++}
++
++TEST(array_copy)
++{
++ const int iterations = 1529; /* this is arbitrary */
++ struct wl_array source;
++ struct wl_array copy;
++ int i;
++
++ wl_array_init(&source);
++
++ /* add some data */
++ for (i = 0; i < iterations; i++) {
++ int *p = wl_array_add(&source, sizeof(int));
++ assert(p);
++ *p = i * 2 + i;
++ }
++
++ /* copy the array */
++ wl_array_init(©);
++ wl_array_copy(©, &source);
++
++ /* check the copy */
++ for (i = 0; i < iterations; i++) {
++ int *s = (int *)source.data + i;
++ int *c = (int *)copy.data + i;
++
++ assert(*s == *c); /* verify the values are the same */
++ assert(s != c); /* ensure the addresses aren't the same */
++ assert(*s == i * 2 + i); /* sanity check */
++ }
++
++ wl_array_release(&source);
++ wl_array_release(©);
++}
++
++TEST(array_for_each)
++{
++ static const int elements[] = { 77, 12, 45192, 53280, 334455 };
++ struct wl_array array;
++ int *p;
++ int i;
++
++ wl_array_init(&array);
++ for (i = 0; i < 5; i++) {
++ p = wl_array_add(&array, sizeof *p);
++ assert(p);
++ *p = elements[i];
++ }
++
++ i = 0;
++ wl_array_for_each(p, &array) {
++ assert(*p == elements[i]);
++ i++;
++ }
++ assert(i == 5);
++
++ wl_array_release(&array);
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdarg.h>
++#include <string.h>
++#include <assert.h>
++#include <sys/socket.h>
++#include <unistd.h>
++#include <errno.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++
++#include "wayland-private.h"
++#include "wayland-server.h"
++#include "test-runner.h"
++
++struct client_destroy_listener {
++ struct wl_listener listener;
++ int done;
++};
++
++static void
++client_destroy_notify(struct wl_listener *l, void *data)
++{
++ struct client_destroy_listener *listener =
++ wl_container_of(l, listener, listener);
++
++ listener->done = 1;
++}
++
++TEST(client_destroy_listener)
++{
++ struct wl_display *display;
++ struct wl_client *client;
++ struct client_destroy_listener a, b;
++ int s[2];
++
++ assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
++ display = wl_display_create();
++ assert(display);
++ client = wl_client_create(display, s[0]);
++ assert(client);
++
++ a.listener.notify = client_destroy_notify;
++ a.done = 0;
++ wl_client_add_destroy_listener(client, &a.listener);
++
++ assert(wl_client_get_destroy_listener(client, client_destroy_notify) ==
++ &a.listener);
++
++ b.listener.notify = client_destroy_notify;
++ b.done = 0;
++ wl_client_add_destroy_listener(client, &b.listener);
++
++ wl_list_remove(&a.listener.link);
++
++ wl_client_destroy(client);
++
++ assert(!a.done);
++ assert(b.done);
++
++ close(s[0]);
++ close(s[1]);
++
++ wl_display_destroy(display);
++}
++
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <assert.h>
++#include <errno.h>
++#include <string.h>
++#include <stdio.h>
++#include <sys/un.h>
++#include <unistd.h>
++
++#include "wayland-client.h"
++#include "wayland-server.h"
++#include "test-runner.h"
++
++/* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */
++static const char *
++require_xdg_runtime_dir(void)
++{
++ char *val = getenv("XDG_RUNTIME_DIR");
++ assert(val && val[0] == '/' && "set $XDG_RUNTIME_DIR to run this test");
++
++ return val;
++}
++
++struct compositor {
++ struct wl_display *display;
++ struct wl_listener listener;
++ struct wl_client *client;
++};
++
++static void
++client_created(struct wl_listener *listener, void *data)
++{
++ struct compositor *c = wl_container_of(listener, c, listener);
++ c->client = data;
++}
++
++static void
++check_client_list(struct compositor *compositor)
++{
++ struct wl_list *client_list;
++ struct wl_client *client, *client_it;
++ int num_clients = 0;
++
++ client_list = wl_display_get_client_list(compositor->display);
++ wl_client_for_each(client_it, client_list) {
++ num_clients++;
++ client = client_it;
++ }
++ assert(num_clients == 1);
++ /* 'client_it' is not valid here, so we took a copy of the client in the loop.
++ * We could also do this assert in the loop directly, but in case it fails it is
++ * easier to understand the problem when we know that the previous assert passed,
++ * so that there is only one client but the wrong one. */
++ assert(compositor->client == client);
++}
++
++static const char *
++setup_compositor(struct compositor *compositor)
++{
++ const char *socket;
++
++ require_xdg_runtime_dir();
++
++ compositor->display = wl_display_create();
++ socket = wl_display_add_socket_auto(compositor->display);
++
++ compositor->listener.notify = client_created;
++ wl_display_add_client_created_listener(compositor->display, &compositor->listener);
++
++ return socket;
++}
++
++static void
++cleanup_compositor(struct compositor *compositor)
++{
++ wl_client_destroy(compositor->client);
++ wl_display_destroy(compositor->display);
++}
++
++TEST(new_client_connect)
++{
++ const char *socket;
++ struct compositor compositor = { 0 };
++ struct {
++ struct wl_display *display;
++ } client;
++
++ socket = setup_compositor(&compositor);
++
++ client.display = wl_display_connect(socket);
++
++ wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100);
++
++ assert(compositor.client != NULL);
++
++ check_client_list(&compositor);
++
++
++
++ wl_display_disconnect(client.display);
++ cleanup_compositor(&compositor);
++}
++
++struct resource_listener {
++ struct wl_listener listener;
++ int count;
++};
++
++static void
++resource_created(struct wl_listener *listener, void *data)
++{
++ struct resource_listener *l;
++ l = wl_container_of(listener, l, listener);
++ l->count++;
++}
++
++TEST(new_resource)
++{
++ const char *socket;
++ struct compositor compositor = { 0 };
++ struct {
++ struct wl_display *display;
++ struct wl_callback *cb;
++ } client;
++ struct resource_listener resource_listener;
++
++ socket = setup_compositor(&compositor);
++ client.display = wl_display_connect(socket);
++ wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100);
++
++ resource_listener.count = 0;
++ resource_listener.listener.notify = resource_created;
++ wl_client_add_resource_created_listener(compositor.client,
++ &resource_listener.listener);
++
++ client.cb = wl_display_sync(client.display);
++ wl_display_flush(client.display);
++ wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100);
++
++ assert(resource_listener.count == 1);
++
++ wl_callback_destroy(client.cb);
++ wl_display_disconnect(client.display);
++ cleanup_compositor(&compositor);
++
++ /* This is defined to be safe also after client destruction */
++ wl_list_remove(&resource_listener.listener.link);
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <math.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdarg.h>
++#include <stdint.h>
++#include <string.h>
++#include <assert.h>
++#include <sys/socket.h>
++#include <unistd.h>
++#include <errno.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <poll.h>
++
++#include "wayland-private.h"
++#include "test-runner.h"
++#include "test-compositor.h"
++
++static const char message[] = "Hello, world";
++
++static struct wl_connection *
++setup(int *s)
++{
++ struct wl_connection *connection;
++
++ assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
++
++ connection = wl_connection_create(s[0]);
++ assert(connection);
++
++ return connection;
++}
++
++TEST(connection_create)
++{
++ struct wl_connection *connection;
++ int s[2];
++
++ connection = setup(s);
++ wl_connection_destroy(connection);
++ close(s[0]);
++ close(s[1]);
++}
++
++TEST(connection_write)
++{
++ struct wl_connection *connection;
++ int s[2];
++ char buffer[64];
++
++ connection = setup(s);
++
++ assert(wl_connection_write(connection, message, sizeof message) == 0);
++ assert(wl_connection_flush(connection) == sizeof message);
++ assert(read(s[1], buffer, sizeof buffer) == sizeof message);
++ assert(memcmp(message, buffer, sizeof message) == 0);
++
++ wl_connection_destroy(connection);
++ close(s[0]);
++ close(s[1]);
++}
++
++TEST(connection_data)
++{
++ struct wl_connection *connection;
++ int s[2];
++ char buffer[64];
++
++ connection = setup(s);
++
++ assert(write(s[1], message, sizeof message) == sizeof message);
++ assert(wl_connection_read(connection) == sizeof message);
++ wl_connection_copy(connection, buffer, sizeof message);
++ assert(memcmp(message, buffer, sizeof message) == 0);
++ wl_connection_consume(connection, sizeof message);
++
++ wl_connection_destroy(connection);
++ close(s[0]);
++ close(s[1]);
++}
++
++TEST(connection_queue)
++{
++ struct wl_connection *connection;
++ int s[2];
++ char buffer[64];
++
++ connection = setup(s);
++
++ /* Test that wl_connection_queue() puts data in the output
++ * buffer without flush it. Verify that the data did get in
++ * the buffer by writing another message and making sure that
++ * we receive the two messages on the other fd. */
++
++ assert(wl_connection_queue(connection, message, sizeof message) == 0);
++ assert(wl_connection_flush(connection) == 0);
++ assert(wl_connection_write(connection, message, sizeof message) == 0);
++ assert(wl_connection_flush(connection) == 2 * sizeof message);
++ assert(read(s[1], buffer, sizeof buffer) == 2 * sizeof message);
++ assert(memcmp(message, buffer, sizeof message) == 0);
++ assert(memcmp(message, buffer + sizeof message, sizeof message) == 0);
++
++ wl_connection_destroy(connection);
++ close(s[0]);
++ close(s[1]);
++}
++
++static void
++va_list_wrapper(const char *signature, union wl_argument *args, int count, ...)
++{
++ va_list ap;
++ va_start(ap, count);
++ wl_argument_from_va_list(signature, args, count, ap);
++ va_end(ap);
++}
++
++TEST(argument_from_va_list)
++{
++ union wl_argument args[WL_CLOSURE_MAX_ARGS];
++ struct wl_object fake_object, fake_new_object;
++ struct wl_array fake_array;
++
++ va_list_wrapper("i", args, 1, 100);
++ assert(args[0].i == 100);
++
++ va_list_wrapper("is", args, 2, 101, "value");
++ assert(args[0].i == 101);
++ assert(strcmp(args[1].s, "value") == 0);
++
++ va_list_wrapper("?iuf?sonah", args, 8,
++ 102, 103, wl_fixed_from_int(104), "value",
++ &fake_object, &fake_new_object, &fake_array, 106);
++ assert(args[0].i == 102);
++ assert(args[1].u == 103);
++ assert(args[2].f == wl_fixed_from_int(104));
++ assert(strcmp(args[3].s, "value") == 0);
++ assert(args[4].o == &fake_object);
++ assert(args[5].o == &fake_new_object);
++ assert(args[6].a == &fake_array);
++ assert(args[7].h == 106);
++}
++
++struct marshal_data {
++ struct wl_connection *read_connection;
++ struct wl_connection *write_connection;
++ int s[2];
++ uint32_t buffer[10];
++ union {
++ uint32_t u;
++ int32_t i;
++ const char *s;
++ int h;
++ } value;
++};
++
++static void
++setup_marshal_data(struct marshal_data *data)
++{
++ assert(socketpair(AF_UNIX,
++ SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
++ data->read_connection = wl_connection_create(data->s[0]);
++ assert(data->read_connection);
++ data->write_connection = wl_connection_create(data->s[1]);
++ assert(data->write_connection);
++}
++
++static void
++release_marshal_data(struct marshal_data *data)
++{
++ close(wl_connection_destroy(data->read_connection));
++ close(wl_connection_destroy(data->write_connection));
++}
++
++static void
++marshal(struct marshal_data *data, const char *format, int size, ...)
++{
++ struct wl_closure *closure;
++ static const uint32_t opcode = 4444;
++ static struct wl_object sender = { NULL, NULL, 1234 };
++ struct wl_message message = { "test", format, NULL };
++ va_list ap;
++
++ va_start(ap, size);
++ closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
++ va_end(ap);
++
++ assert(closure);
++ assert(wl_closure_send(closure, data->write_connection) == 0);
++ wl_closure_destroy(closure);
++ assert(wl_connection_flush(data->write_connection) == size);
++ assert(read(data->s[0], data->buffer, sizeof data->buffer) == size);
++
++ assert(data->buffer[0] == sender.id);
++ assert(data->buffer[1] == (opcode | (size << 16)));
++}
++
++TEST(connection_marshal)
++{
++ struct marshal_data data;
++ struct wl_object object;
++ struct wl_array array;
++ static const char text[] = "curry";
++
++ setup_marshal_data(&data);
++
++ marshal(&data, "i", 12, 42);
++ assert(data.buffer[2] == 42);
++
++ marshal(&data, "u", 12, 55);
++ assert(data.buffer[2] == 55);
++
++ marshal(&data, "s", 20, "frappo");
++ assert(data.buffer[2] == 7);
++ assert(strcmp((char *) &data.buffer[3], "frappo") == 0);
++
++ object.id = 557799;
++ marshal(&data, "o", 12, &object);
++ assert(data.buffer[2] == object.id);
++
++ marshal(&data, "n", 12, &object);
++ assert(data.buffer[2] == object.id);
++
++ array.data = (void *) text;
++ array.size = sizeof text;
++ marshal(&data, "a", 20, &array);
++ assert(data.buffer[2] == array.size);
++ assert(memcmp(&data.buffer[3], text, array.size) == 0);
++
++ release_marshal_data(&data);
++}
++
++static void
++expected_fail_marshal(int expected_error, const char *format, ...)
++{
++ struct wl_closure *closure;
++ static const uint32_t opcode = 4444;
++ static const struct wl_interface test_interface = {
++ .name = "test_object"
++ };
++ static struct wl_object sender = { 0 };
++ struct wl_message message = { "test", format, NULL };
++
++ sender.interface = &test_interface;
++ sender.id = 1234;
++ va_list ap;
++
++ va_start(ap, format);
++ closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
++ va_end(ap);
++
++ assert(closure == NULL);
++ assert(errno == expected_error);
++}
++
++static void
++expected_fail_marshal_send(struct marshal_data *data, int expected_error,
++ const char *format, ...)
++{
++ struct wl_closure *closure;
++ static const uint32_t opcode = 4444;
++ static struct wl_object sender = { NULL, NULL, 1234 };
++ struct wl_message message = { "test", format, NULL };
++ va_list ap;
++
++ va_start(ap, format);
++ closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
++ va_end(ap);
++
++ assert(closure);
++ assert(wl_closure_send(closure, data->write_connection) < 0);
++ assert(errno == expected_error);
++
++ wl_closure_destroy(closure);
++}
++
++TEST(connection_marshal_nullables)
++{
++ struct marshal_data data;
++ struct wl_object object;
++ const char text[] = "curry";
++
++ setup_marshal_data(&data);
++
++ expected_fail_marshal(EINVAL, "o", NULL);
++ expected_fail_marshal(EINVAL, "s", NULL);
++ expected_fail_marshal(EINVAL, "a", NULL);
++
++ marshal(&data, "?o", 12, NULL);
++ assert(data.buffer[2] == 0);
++
++ marshal(&data, "?s", 12, NULL);
++ assert(data.buffer[2] == 0);
++
++ object.id = 55293;
++ marshal(&data, "?o", 12, &object);
++ assert(data.buffer[2] == object.id);
++
++ marshal(&data, "?s", 20, text);
++ assert(data.buffer[2] == sizeof text);
++ assert(strcmp((char *) &data.buffer[3], text) == 0);
++
++ release_marshal_data(&data);
++}
++
++static void
++validate_demarshal_u(struct marshal_data *data,
++ struct wl_object *object, uint32_t u)
++{
++ assert(data->value.u == u);
++}
++
++static void
++validate_demarshal_i(struct marshal_data *data,
++ struct wl_object *object, int32_t i)
++{
++ assert(data->value.i == i);
++}
++
++static void
++validate_demarshal_s(struct marshal_data *data,
++ struct wl_object *object, const char *s)
++{
++ if (data->value.s != NULL)
++ assert(strcmp(data->value.s, s) == 0);
++ else
++ assert(s == NULL);
++}
++
++static void
++validate_demarshal_h(struct marshal_data *data,
++ struct wl_object *object, int fd)
++{
++ struct stat buf1, buf2;
++
++ assert(fd != data->value.h);
++ fstat(fd, &buf1);
++ fstat(data->value.h, &buf2);
++ assert(buf1.st_dev == buf2.st_dev);
++ assert(buf1.st_ino == buf2.st_ino);
++ close(fd);
++ close(data->value.h);
++}
++
++static void
++validate_demarshal_f(struct marshal_data *data,
++ struct wl_object *object, wl_fixed_t f)
++{
++ assert(data->value.i == f);
++}
++
++static void
++demarshal(struct marshal_data *data, const char *format,
++ uint32_t *msg, void (*func)(void))
++{
++ struct wl_message message = { "test", format, NULL };
++ struct wl_closure *closure;
++ struct wl_map objects;
++ struct wl_object object = { NULL, &func, 0 };
++ int size = msg[1] >> 16;
++
++ assert(write(data->s[1], msg, size) == size);
++ assert(wl_connection_read(data->read_connection) == size);
++
++ wl_map_init(&objects, WL_MAP_SERVER_SIDE);
++ object.id = msg[0];
++ closure = wl_connection_demarshal(data->read_connection,
++ size, &objects, &message);
++ assert(closure);
++ wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, &object, 0, data);
++ wl_closure_destroy(closure);
++}
++
++TEST(connection_demarshal)
++{
++ struct marshal_data data;
++ uint32_t msg[10];
++
++ setup_marshal_data(&data);
++
++ data.value.u = 8000;
++ msg[0] = 400200; /* object id */
++ msg[1] = 12 << 16; /* size = 12, opcode = 0 */
++ msg[2] = data.value.u;
++ demarshal(&data, "u", msg, (void *) validate_demarshal_u);
++
++ data.value.i = -557799;
++ msg[0] = 400200;
++ msg[1] = 12 << 16;
++ msg[2] = data.value.i;
++ demarshal(&data, "i", msg, (void *) validate_demarshal_i);
++
++ data.value.s = "superdude";
++ msg[0] = 400200;
++ msg[1] = 24 << 16;
++ msg[2] = 10;
++ msg[3 + msg[2]/4] = 0;
++ memcpy(&msg[3], data.value.s, msg[2]);
++ demarshal(&data, "s", msg, (void *) validate_demarshal_s);
++
++ data.value.s = "superdude";
++ msg[0] = 400200;
++ msg[1] = 24 << 16;
++ msg[2] = 10;
++ msg[3 + msg[2]/4] = 0;
++ memcpy(&msg[3], data.value.s, msg[2]);
++ demarshal(&data, "?s", msg, (void *) validate_demarshal_s);
++
++ data.value.i = wl_fixed_from_double(-90000.2390);
++ msg[0] = 400200;
++ msg[1] = 12 << 16;
++ msg[2] = data.value.i;
++ demarshal(&data, "f", msg, (void *) validate_demarshal_f);
++
++ data.value.s = NULL;
++ msg[0] = 400200;
++ msg[1] = 12 << 16;
++ msg[2] = 0;
++ demarshal(&data, "?s", msg, (void *) validate_demarshal_s);
++
++ release_marshal_data(&data);
++}
++
++static void
++marshal_demarshal(struct marshal_data *data,
++ void (*func)(void), int size, const char *format, ...)
++{
++ struct wl_closure *closure;
++ static const int opcode = 4444;
++ static struct wl_object sender = { NULL, NULL, 1234 };
++ struct wl_message message = { "test", format, NULL };
++ struct wl_map objects;
++ struct wl_object object = { NULL, &func, 0 };
++ va_list ap;
++ uint32_t msg[1] = { 1234 };
++
++ va_start(ap, format);
++ closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
++ va_end(ap);
++
++ assert(closure);
++ assert(wl_closure_send(closure, data->write_connection) == 0);
++ wl_closure_destroy(closure);
++ assert(wl_connection_flush(data->write_connection) == size);
++
++ assert(wl_connection_read(data->read_connection) == size);
++
++ wl_map_init(&objects, WL_MAP_SERVER_SIDE);
++ object.id = msg[0];
++ closure = wl_connection_demarshal(data->read_connection,
++ size, &objects, &message);
++ assert(closure);
++ wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, &object, 0, data);
++ wl_closure_destroy(closure);
++}
++
++TEST(connection_marshal_demarshal)
++{
++ struct marshal_data data;
++ char f[] = "/tmp/wayland-tests-XXXXXX";
++
++ setup_marshal_data(&data);
++
++ data.value.u = 889911;
++ marshal_demarshal(&data, (void *) validate_demarshal_u,
++ 12, "u", data.value.u);
++
++ data.value.i = -13;
++ marshal_demarshal(&data, (void *) validate_demarshal_i,
++ 12, "i", data.value.i);
++
++ data.value.s = "cookie robots";
++ marshal_demarshal(&data, (void *) validate_demarshal_s,
++ 28, "s", data.value.s);
++
++ data.value.s = "cookie robots";
++ marshal_demarshal(&data, (void *) validate_demarshal_s,
++ 28, "?s", data.value.s);
++
++ data.value.h = mkstemp(f);
++ assert(data.value.h >= 0);
++ unlink(f);
++ marshal_demarshal(&data, (void *) validate_demarshal_h,
++ 8, "h", data.value.h);
++
++ data.value.i = wl_fixed_from_double(1234.5678);
++ marshal_demarshal(&data, (void *) validate_demarshal_f,
++ 12, "f", data.value.i);
++
++ data.value.i = wl_fixed_from_double(-90000.2390);
++ marshal_demarshal(&data, (void *) validate_demarshal_f,
++ 12, "f", data.value.i);
++
++ data.value.i = wl_fixed_from_double((1 << 23) - 1 + 0.0941);
++ marshal_demarshal(&data, (void *) validate_demarshal_f,
++ 12, "f", data.value.i);
++
++ release_marshal_data(&data);
++}
++
++static void
++expected_fail_demarshal(struct marshal_data *data, const char *format,
++ const uint32_t *msg, int expected_error)
++{
++ struct wl_message message = { "test", format, NULL };
++ struct wl_closure *closure;
++ struct wl_map objects;
++ int size = (msg[1] >> 16);
++
++ assert(write(data->s[1], msg, size) == size);
++ assert(wl_connection_read(data->read_connection) == size);
++
++ wl_map_init(&objects, WL_MAP_SERVER_SIDE);
++ closure = wl_connection_demarshal(data->read_connection,
++ size, &objects, &message);
++
++ assert(closure == NULL);
++ assert(errno == expected_error);
++}
++
++TEST(connection_demarshal_null_strings)
++{
++ struct marshal_data data;
++ uint32_t msg[3];
++
++ setup_marshal_data(&data);
++
++ data.value.s = NULL;
++ msg[0] = 400200; /* object id */
++ msg[1] = 12 << 16; /* size = 12, opcode = 0 */
++ msg[2] = 0; /* string length = 0 */
++ demarshal(&data, "?s", msg, (void *) validate_demarshal_s);
++
++ expected_fail_demarshal(&data, "s", msg, EINVAL);
++
++ release_marshal_data(&data);
++}
++
++/* These tests are verifying that the demarshaling code will gracefully handle
++ * clients lying about string and array lengths and giving values near
++ * UINT32_MAX. Before fixes f7fdface and f5b9e3b9 this test would crash on
++ * 32bit systems.
++ */
++TEST(connection_demarshal_failures)
++{
++ struct marshal_data data;
++ unsigned int i;
++ uint32_t msg[3];
++
++ const uint32_t overflowing_values[] = {
++ /* Values very close to UINT32_MAX. Before f5b9e3b9 these
++ * would cause integer overflow in DIV_ROUNDUP. */
++ 0xffffffff, 0xfffffffe, 0xfffffffd, 0xfffffffc,
++
++ /* Values at various offsets from UINT32_MAX. Before f7fdface
++ * these would overflow the "p" pointer on 32bit systems,
++ * effectively subtracting the offset from it. It had good
++ * chance to cause crash depending on what was stored at that
++ * offset before "p". */
++ 0xfffff000, 0xffffd000, 0xffffc000, 0xffffb000
++ };
++
++ setup_marshal_data(&data);
++
++ /* sender_id, does not matter */
++ msg[0] = 0;
++
++ /* (size << 16 | opcode), opcode is 0, does not matter */
++ msg[1] = sizeof(msg) << 16;
++
++ for (i = 0; i < ARRAY_LENGTH(overflowing_values); i++) {
++ /* length of the string or array */
++ msg[2] = overflowing_values[i];
++
++ expected_fail_demarshal(&data, "s", msg, EINVAL);
++ expected_fail_demarshal(&data, "a", msg, EINVAL);
++ }
++
++ release_marshal_data(&data);
++}
++
++TEST(connection_marshal_alot)
++{
++ struct marshal_data data;
++ char f[64];
++ int i;
++
++ setup_marshal_data(&data);
++
++ /* We iterate enough to make sure we wrap the circular buffers
++ * for both regular data an fds. */
++
++ for (i = 0; i < 2000; i++) {
++ strcpy(f, "/tmp/wayland-tests-XXXXXX");
++ data.value.h = mkstemp(f);
++ assert(data.value.h >= 0);
++ unlink(f);
++ marshal_demarshal(&data, (void *) validate_demarshal_h,
++ 8, "h", data.value.h);
++ }
++
++ release_marshal_data(&data);
++}
++
++TEST(connection_marshal_too_big)
++{
++ struct marshal_data data;
++ char *big_string = malloc(5000);
++
++ assert(big_string);
++
++ memset(big_string, ' ', 4999);
++ big_string[4999] = '\0';
++
++ setup_marshal_data(&data);
++
++ expected_fail_marshal_send(&data, E2BIG, "s", big_string);
++
++ release_marshal_data(&data);
++ free(big_string);
++}
++
++static void
++marshal_helper(const char *format, void *handler, ...)
++{
++ struct wl_closure *closure;
++ static struct wl_object sender = { NULL, NULL, 1234 };
++ struct wl_object object = { NULL, &handler, 0 };
++ static const int opcode = 4444;
++ struct wl_message message = { "test", format, NULL };
++ va_list ap;
++ int done;
++
++ va_start(ap, handler);
++ closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
++ va_end(ap);
++
++ assert(closure);
++ done = 0;
++ wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, &object, 0, &done);
++ wl_closure_destroy(closure);
++ assert(done);
++}
++
++static void
++suu_handler(void *data, struct wl_object *object,
++ const char *s, uint32_t u1, uint32_t u2)
++{
++ int *done = data;
++
++ assert(strcmp(s, "foo") == 0);
++ assert(u1 == 500);
++ assert(u2 == 404040);
++ *done = 1;
++}
++
++TEST(invoke_closure)
++{
++ marshal_helper("suu", suu_handler, "foo", 500, 404040);
++}
++
++static void
++leak_closure(void)
++{
++ struct wl_callback *cb;
++ struct pollfd pfd;
++ struct client *c = client_connect();
++
++ cb = wl_display_sync(c->wl_display);
++ assert(cb);
++ assert(wl_display_flush(c->wl_display) > 0);
++
++ /* we don't need it, it is referenced */
++ wl_callback_destroy(cb);
++
++ pfd.fd = wl_display_get_fd(c->wl_display);
++ pfd.events = POLLIN;
++
++ test_set_timeout(2);
++ assert(poll(&pfd, 1, -1) == 1);
++
++ /* read events, but do not dispatch them */
++ assert(wl_display_prepare_read(c->wl_display) == 0);
++ assert(wl_display_read_events(c->wl_display) == 0);
++
++ /*
++ * now we have wl_callback.done and wl_display.delete_id queued;
++ * if we now release the queue (in wl_display_disconnect())
++ * we should not leak memory
++ */
++
++ client_disconnect(c);
++}
++
++TEST(closure_leaks)
++{
++ struct display *d = display_create();
++
++ client_create_noarg(d, leak_closure);
++ display_run(d);
++
++ display_destroy(d);
++}
++
++static void
++leak_after_error(void)
++{
++ struct client *c = client_connect();
++
++ /* this should return -1, because we'll send error
++ * from server. */
++ assert(stop_display(c, 1) == -1);
++ assert(wl_display_dispatch_pending(c->wl_display) == -1);
++ assert(wl_display_get_error(c->wl_display) == ENOMEM);
++
++ /* after we got error, we have display_resume event
++ * in the queue. It should be freed in wl_display_disconnect().
++ * Let's see! */
++
++ wl_proxy_destroy((struct wl_proxy *) c->tc);
++ wl_display_disconnect(c->wl_display);
++ free(c);
++}
++
++TEST(closure_leaks_after_error)
++{
++ struct display *d = display_create();
++ struct client_info *cl;
++
++ cl = client_create_noarg(d, leak_after_error);
++ display_run(d);
++
++ wl_client_post_no_memory(cl->wl_client);
++ display_resume(d);
++
++ display_destroy(d);
++}
++
++/** Raw read from socket expecting wl_display.error
++ *
++ * \param sockfd The socket to read from.
++ * \param expected_error The expected wl_display error code.
++ *
++ * Reads the socket and manually parses one message, expecting it to be a
++ * wl_display.error with the wl_display as the originating object.
++ * Asserts that the received error code is expected_error.
++ */
++static void
++expect_error_recv(int sockfd, uint32_t expected_error)
++{
++ uint32_t buf[1024];
++ ssize_t slen;
++ uint32_t opcode;
++ int str_len;
++
++ slen = recv(sockfd, buf, sizeof buf, 0);
++ assert(slen >= 2 * (ssize_t)sizeof (uint32_t));
++ opcode = buf[1] & 0xffff;
++ fprintf(stderr, "Received %zd bytes, object %u, opcode %u\n",
++ slen, buf[0], opcode);
++
++ /* check error event */
++ assert(buf[0] == 1);
++ assert(opcode == WL_DISPLAY_ERROR);
++
++ str_len = buf[4];
++ assert(str_len > 0);
++ assert(str_len <= slen - 5 * (ssize_t)sizeof (uint32_t));
++ fprintf(stderr, "Error event on object %u, code %u, message \"%*s\"\n",
++ buf[2], buf[3], str_len, (const char *)&buf[5]);
++
++ assert(buf[3] == expected_error);
++}
++
++/* A test for https://gitlab.freedesktop.org/wayland/wayland/issues/52
++ * trying to provoke a read from uninitialized memory in
++ * wl_connection_demarshal() for sender_id and opcode.
++ *
++ * This test might not fail as is even with #52 unfixed, since there is no way
++ * to detect what happens and the crash with zero size depends on stack content.
++ * However, running under Valgrind would point out invalid reads and use of
++ * uninitialized values.
++ */
++TEST(request_bogus_size)
++{
++ struct wl_display *display;
++ struct wl_client *client;
++ int s[2];
++ uint32_t msg[3];
++ int bogus_size;
++
++ test_set_timeout(1);
++
++ /*
++ * The manufactured message has real size 12. Test all bogus sizes
++ * smaller than that, and zero as the last one since wl_closure_init
++ * handles zero specially and having garbage in the stack makes it more
++ * likely to crash in wl_connection_demarshal.
++ */
++ for (bogus_size = 11; bogus_size >= 0; bogus_size--) {
++ fprintf(stderr, "* bogus size %d\n", bogus_size);
++
++ assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
++ display = wl_display_create();
++ assert(display);
++ client = wl_client_create(display, s[0]);
++ assert(client);
++
++ /* manufacture a request that lies about its size */
++ msg[0] = 1; /* sender id: wl_display */
++ msg[1] = (bogus_size << 16) | WL_DISPLAY_SYNC; /* size and opcode */
++ msg[2] = 2; /* sync argument: new_id for wl_callback */
++
++ assert(send(s[1], msg, sizeof msg, 0) == sizeof msg);
++
++ wl_event_loop_dispatch(wl_display_get_event_loop(display), 0);
++
++ expect_error_recv(s[1], WL_DISPLAY_ERROR_INVALID_METHOD);
++
++ /* Do not wl_client_destroy, the error already caused it. */
++ close(s[1]);
++ wl_display_destroy(display);
++ }
++}
--- /dev/null
--- /dev/null
++/* This source should compile fine with C++ compiler */
++#include "wayland-server-protocol.h"
++
++int main() { return 0; }
++
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="the_protocol">
++ <interface name="the_interface" version="1">
++ <description summary="the summary">
++ </description>
++ <request name="the_request">
++ <arg name="" type="uint"/>
++ </request>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="the_protocol">
++ <interface name="the_interface" version="1">
++ <description summary="the summary">
++ </description>
++ <enum name="4the_enum">
++ <entry name="60_seconds" value="1" summary="this is the first"/>
++ <entry name="invalid entry" value="2" summary="this is the first"/>
++ </enum>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="the_protocol">
++ <interface name="the_interface" version="1">
++ <description summary="the summary">
++ </description>
++ <enum name="the-enum">
++ <entry name="the_entry" value="0" summary="entry summary"/>
++ </enum>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="the_protocol">
++ <interface name="the_interface" version="1">
++ <description summary="the summary">
++ </description>
++ <event name="theΔevent"/>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="the_protocol">
++ <interface name="inter face" version="1">
++ <description summary="the summary">
++ </description>
++ <event name="the_event"/>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="1badprotocol">
++ <interface name="required_interface" version="13">
++ <description summary="required summary">
++ </description>
++ <event name="requied_event"/>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="the_protocol">
++ <interface name="the_interface" version="1">
++ <description summary="the summary">
++ </description>
++ <request name="req-west">
++ <arg name="the_arg" type="uint"/>
++ </request>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++/* SCANNER TEST */
++
++#ifndef WAYLAND_CLIENT_PROTOCOL_H
++#define WAYLAND_CLIENT_PROTOCOL_H
++
++#include <stdint.h>
++#include <stddef.h>
++#include "wayland-client.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * @page page_wayland The wayland protocol
++ * @section page_ifaces_wayland Interfaces
++ * - @subpage page_iface_wl_display - core global object
++ * - @subpage page_iface_wl_registry - global registry object
++ * - @subpage page_iface_wl_callback - callback object
++ * - @subpage page_iface_wl_compositor - the compositor singleton
++ * - @subpage page_iface_wl_shm_pool - a shared memory pool
++ * - @subpage page_iface_wl_shm - shared memory support
++ * - @subpage page_iface_wl_buffer - content for a wl_surface
++ * - @subpage page_iface_wl_data_offer - offer to transfer data
++ * - @subpage page_iface_wl_data_source - offer to transfer data
++ * - @subpage page_iface_wl_data_device - data transfer device
++ * - @subpage page_iface_wl_data_device_manager - data transfer interface
++ * - @subpage page_iface_wl_shell - create desktop-style surfaces
++ * - @subpage page_iface_wl_shell_surface - desktop-style metadata interface
++ * - @subpage page_iface_wl_surface - an onscreen surface
++ * - @subpage page_iface_wl_seat - group of input devices
++ * - @subpage page_iface_wl_pointer - pointer input device
++ * - @subpage page_iface_wl_keyboard - keyboard input device
++ * - @subpage page_iface_wl_touch - touchscreen input device
++ * - @subpage page_iface_wl_output - compositor output region
++ * - @subpage page_iface_wl_region - region interface
++ * - @subpage page_iface_wl_subcompositor - sub-surface compositing
++ * - @subpage page_iface_wl_subsurface - sub-surface interface to a wl_surface
++ * @section page_copyright_wayland Copyright
++ * <pre>
++ *
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2010-2011 Intel Corporation
++ * Copyright © 2012-2013 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ * </pre>
++ */
++struct wl_buffer;
++struct wl_callback;
++struct wl_compositor;
++struct wl_data_device;
++struct wl_data_device_manager;
++struct wl_data_offer;
++struct wl_data_source;
++struct wl_display;
++struct wl_keyboard;
++struct wl_output;
++struct wl_pointer;
++struct wl_region;
++struct wl_registry;
++struct wl_seat;
++struct wl_shell;
++struct wl_shell_surface;
++struct wl_shm;
++struct wl_shm_pool;
++struct wl_subcompositor;
++struct wl_subsurface;
++struct wl_surface;
++struct wl_touch;
++
++#ifndef WL_DISPLAY_INTERFACE
++#define WL_DISPLAY_INTERFACE
++/**
++ * @page page_iface_wl_display wl_display
++ * @section page_iface_wl_display_desc Description
++ *
++ * The core global object. This is a special singleton object. It
++ * is used for internal Wayland protocol features.
++ * @section page_iface_wl_display_api API
++ * See @ref iface_wl_display.
++ */
++/**
++ * @defgroup iface_wl_display The wl_display interface
++ *
++ * The core global object. This is a special singleton object. It
++ * is used for internal Wayland protocol features.
++ */
++extern const struct wl_interface wl_display_interface;
++#endif
++#ifndef WL_REGISTRY_INTERFACE
++#define WL_REGISTRY_INTERFACE
++/**
++ * @page page_iface_wl_registry wl_registry
++ * @section page_iface_wl_registry_desc Description
++ *
++ * The singleton global registry object. The server has a number of
++ * global objects that are available to all clients. These objects
++ * typically represent an actual object in the server (for example,
++ * an input device) or they are singleton objects that provide
++ * extension functionality.
++ *
++ * When a client creates a registry object, the registry object
++ * will emit a global event for each global currently in the
++ * registry. Globals come and go as a result of device or
++ * monitor hotplugs, reconfiguration or other events, and the
++ * registry will send out global and global_remove events to
++ * keep the client up to date with the changes. To mark the end
++ * of the initial burst of events, the client can use the
++ * wl_display.sync request immediately after calling
++ * wl_display.get_registry.
++ *
++ * A client can bind to a global object by using the bind
++ * request. This creates a client-side handle that lets the object
++ * emit events to the client and lets the client invoke requests on
++ * the object.
++ * @section page_iface_wl_registry_api API
++ * See @ref iface_wl_registry.
++ */
++/**
++ * @defgroup iface_wl_registry The wl_registry interface
++ *
++ * The singleton global registry object. The server has a number of
++ * global objects that are available to all clients. These objects
++ * typically represent an actual object in the server (for example,
++ * an input device) or they are singleton objects that provide
++ * extension functionality.
++ *
++ * When a client creates a registry object, the registry object
++ * will emit a global event for each global currently in the
++ * registry. Globals come and go as a result of device or
++ * monitor hotplugs, reconfiguration or other events, and the
++ * registry will send out global and global_remove events to
++ * keep the client up to date with the changes. To mark the end
++ * of the initial burst of events, the client can use the
++ * wl_display.sync request immediately after calling
++ * wl_display.get_registry.
++ *
++ * A client can bind to a global object by using the bind
++ * request. This creates a client-side handle that lets the object
++ * emit events to the client and lets the client invoke requests on
++ * the object.
++ */
++extern const struct wl_interface wl_registry_interface;
++#endif
++#ifndef WL_CALLBACK_INTERFACE
++#define WL_CALLBACK_INTERFACE
++/**
++ * @page page_iface_wl_callback wl_callback
++ * @section page_iface_wl_callback_desc Description
++ *
++ * Clients can handle the 'done' event to get notified when
++ * the related request is done.
++ * @section page_iface_wl_callback_api API
++ * See @ref iface_wl_callback.
++ */
++/**
++ * @defgroup iface_wl_callback The wl_callback interface
++ *
++ * Clients can handle the 'done' event to get notified when
++ * the related request is done.
++ */
++extern const struct wl_interface wl_callback_interface;
++#endif
++#ifndef WL_COMPOSITOR_INTERFACE
++#define WL_COMPOSITOR_INTERFACE
++/**
++ * @page page_iface_wl_compositor wl_compositor
++ * @section page_iface_wl_compositor_desc Description
++ *
++ * A compositor. This object is a singleton global. The
++ * compositor is in charge of combining the contents of multiple
++ * surfaces into one displayable output.
++ * @section page_iface_wl_compositor_api API
++ * See @ref iface_wl_compositor.
++ */
++/**
++ * @defgroup iface_wl_compositor The wl_compositor interface
++ *
++ * A compositor. This object is a singleton global. The
++ * compositor is in charge of combining the contents of multiple
++ * surfaces into one displayable output.
++ */
++extern const struct wl_interface wl_compositor_interface;
++#endif
++#ifndef WL_SHM_POOL_INTERFACE
++#define WL_SHM_POOL_INTERFACE
++/**
++ * @page page_iface_wl_shm_pool wl_shm_pool
++ * @section page_iface_wl_shm_pool_desc Description
++ *
++ * The wl_shm_pool object encapsulates a piece of memory shared
++ * between the compositor and client. Through the wl_shm_pool
++ * object, the client can allocate shared memory wl_buffer objects.
++ * All objects created through the same pool share the same
++ * underlying mapped memory. Reusing the mapped memory avoids the
++ * setup/teardown overhead and is useful when interactively resizing
++ * a surface or for many small buffers.
++ * @section page_iface_wl_shm_pool_api API
++ * See @ref iface_wl_shm_pool.
++ */
++/**
++ * @defgroup iface_wl_shm_pool The wl_shm_pool interface
++ *
++ * The wl_shm_pool object encapsulates a piece of memory shared
++ * between the compositor and client. Through the wl_shm_pool
++ * object, the client can allocate shared memory wl_buffer objects.
++ * All objects created through the same pool share the same
++ * underlying mapped memory. Reusing the mapped memory avoids the
++ * setup/teardown overhead and is useful when interactively resizing
++ * a surface or for many small buffers.
++ */
++extern const struct wl_interface wl_shm_pool_interface;
++#endif
++#ifndef WL_SHM_INTERFACE
++#define WL_SHM_INTERFACE
++/**
++ * @page page_iface_wl_shm wl_shm
++ * @section page_iface_wl_shm_desc Description
++ *
++ * A singleton global object that provides support for shared
++ * memory.
++ *
++ * Clients can create wl_shm_pool objects using the create_pool
++ * request.
++ *
++ * At connection setup time, the wl_shm object emits one or more
++ * format events to inform clients about the valid pixel formats
++ * that can be used for buffers.
++ * @section page_iface_wl_shm_api API
++ * See @ref iface_wl_shm.
++ */
++/**
++ * @defgroup iface_wl_shm The wl_shm interface
++ *
++ * A singleton global object that provides support for shared
++ * memory.
++ *
++ * Clients can create wl_shm_pool objects using the create_pool
++ * request.
++ *
++ * At connection setup time, the wl_shm object emits one or more
++ * format events to inform clients about the valid pixel formats
++ * that can be used for buffers.
++ */
++extern const struct wl_interface wl_shm_interface;
++#endif
++#ifndef WL_BUFFER_INTERFACE
++#define WL_BUFFER_INTERFACE
++/**
++ * @page page_iface_wl_buffer wl_buffer
++ * @section page_iface_wl_buffer_desc Description
++ *
++ * A buffer provides the content for a wl_surface. Buffers are
++ * created through factory interfaces such as wl_drm, wl_shm or
++ * similar. It has a width and a height and can be attached to a
++ * wl_surface, but the mechanism by which a client provides and
++ * updates the contents is defined by the buffer factory interface.
++ * @section page_iface_wl_buffer_api API
++ * See @ref iface_wl_buffer.
++ */
++/**
++ * @defgroup iface_wl_buffer The wl_buffer interface
++ *
++ * A buffer provides the content for a wl_surface. Buffers are
++ * created through factory interfaces such as wl_drm, wl_shm or
++ * similar. It has a width and a height and can be attached to a
++ * wl_surface, but the mechanism by which a client provides and
++ * updates the contents is defined by the buffer factory interface.
++ */
++extern const struct wl_interface wl_buffer_interface;
++#endif
++#ifndef WL_DATA_OFFER_INTERFACE
++#define WL_DATA_OFFER_INTERFACE
++/**
++ * @page page_iface_wl_data_offer wl_data_offer
++ * @section page_iface_wl_data_offer_desc Description
++ *
++ * A wl_data_offer represents a piece of data offered for transfer
++ * by another client (the source client). It is used by the
++ * copy-and-paste and drag-and-drop mechanisms. The offer
++ * describes the different mime types that the data can be
++ * converted to and provides the mechanism for transferring the
++ * data directly from the source client.
++ * @section page_iface_wl_data_offer_api API
++ * See @ref iface_wl_data_offer.
++ */
++/**
++ * @defgroup iface_wl_data_offer The wl_data_offer interface
++ *
++ * A wl_data_offer represents a piece of data offered for transfer
++ * by another client (the source client). It is used by the
++ * copy-and-paste and drag-and-drop mechanisms. The offer
++ * describes the different mime types that the data can be
++ * converted to and provides the mechanism for transferring the
++ * data directly from the source client.
++ */
++extern const struct wl_interface wl_data_offer_interface;
++#endif
++#ifndef WL_DATA_SOURCE_INTERFACE
++#define WL_DATA_SOURCE_INTERFACE
++/**
++ * @page page_iface_wl_data_source wl_data_source
++ * @section page_iface_wl_data_source_desc Description
++ *
++ * The wl_data_source object is the source side of a wl_data_offer.
++ * It is created by the source client in a data transfer and
++ * provides a way to describe the offered data and a way to respond
++ * to requests to transfer the data.
++ * @section page_iface_wl_data_source_api API
++ * See @ref iface_wl_data_source.
++ */
++/**
++ * @defgroup iface_wl_data_source The wl_data_source interface
++ *
++ * The wl_data_source object is the source side of a wl_data_offer.
++ * It is created by the source client in a data transfer and
++ * provides a way to describe the offered data and a way to respond
++ * to requests to transfer the data.
++ */
++extern const struct wl_interface wl_data_source_interface;
++#endif
++#ifndef WL_DATA_DEVICE_INTERFACE
++#define WL_DATA_DEVICE_INTERFACE
++/**
++ * @page page_iface_wl_data_device wl_data_device
++ * @section page_iface_wl_data_device_desc Description
++ *
++ * There is one wl_data_device per seat which can be obtained
++ * from the global wl_data_device_manager singleton.
++ *
++ * A wl_data_device provides access to inter-client data transfer
++ * mechanisms such as copy-and-paste and drag-and-drop.
++ * @section page_iface_wl_data_device_api API
++ * See @ref iface_wl_data_device.
++ */
++/**
++ * @defgroup iface_wl_data_device The wl_data_device interface
++ *
++ * There is one wl_data_device per seat which can be obtained
++ * from the global wl_data_device_manager singleton.
++ *
++ * A wl_data_device provides access to inter-client data transfer
++ * mechanisms such as copy-and-paste and drag-and-drop.
++ */
++extern const struct wl_interface wl_data_device_interface;
++#endif
++#ifndef WL_DATA_DEVICE_MANAGER_INTERFACE
++#define WL_DATA_DEVICE_MANAGER_INTERFACE
++/**
++ * @page page_iface_wl_data_device_manager wl_data_device_manager
++ * @section page_iface_wl_data_device_manager_desc Description
++ *
++ * The wl_data_device_manager is a singleton global object that
++ * provides access to inter-client data transfer mechanisms such as
++ * copy-and-paste and drag-and-drop. These mechanisms are tied to
++ * a wl_seat and this interface lets a client get a wl_data_device
++ * corresponding to a wl_seat.
++ *
++ * Depending on the version bound, the objects created from the bound
++ * wl_data_device_manager object will have different requirements for
++ * functioning properly. See wl_data_source.set_actions,
++ * wl_data_offer.accept and wl_data_offer.finish for details.
++ * @section page_iface_wl_data_device_manager_api API
++ * See @ref iface_wl_data_device_manager.
++ */
++/**
++ * @defgroup iface_wl_data_device_manager The wl_data_device_manager interface
++ *
++ * The wl_data_device_manager is a singleton global object that
++ * provides access to inter-client data transfer mechanisms such as
++ * copy-and-paste and drag-and-drop. These mechanisms are tied to
++ * a wl_seat and this interface lets a client get a wl_data_device
++ * corresponding to a wl_seat.
++ *
++ * Depending on the version bound, the objects created from the bound
++ * wl_data_device_manager object will have different requirements for
++ * functioning properly. See wl_data_source.set_actions,
++ * wl_data_offer.accept and wl_data_offer.finish for details.
++ */
++extern const struct wl_interface wl_data_device_manager_interface;
++#endif
++#ifndef WL_SHELL_INTERFACE
++#define WL_SHELL_INTERFACE
++/**
++ * @page page_iface_wl_shell wl_shell
++ * @section page_iface_wl_shell_desc Description
++ *
++ * This interface is implemented by servers that provide
++ * desktop-style user interfaces.
++ *
++ * It allows clients to associate a wl_shell_surface with
++ * a basic surface.
++ * @section page_iface_wl_shell_api API
++ * See @ref iface_wl_shell.
++ */
++/**
++ * @defgroup iface_wl_shell The wl_shell interface
++ *
++ * This interface is implemented by servers that provide
++ * desktop-style user interfaces.
++ *
++ * It allows clients to associate a wl_shell_surface with
++ * a basic surface.
++ */
++extern const struct wl_interface wl_shell_interface;
++#endif
++#ifndef WL_SHELL_SURFACE_INTERFACE
++#define WL_SHELL_SURFACE_INTERFACE
++/**
++ * @page page_iface_wl_shell_surface wl_shell_surface
++ * @section page_iface_wl_shell_surface_desc Description
++ *
++ * An interface that may be implemented by a wl_surface, for
++ * implementations that provide a desktop-style user interface.
++ *
++ * It provides requests to treat surfaces like toplevel, fullscreen
++ * or popup windows, move, resize or maximize them, associate
++ * metadata like title and class, etc.
++ *
++ * On the server side the object is automatically destroyed when
++ * the related wl_surface is destroyed. On the client side,
++ * wl_shell_surface_destroy() must be called before destroying
++ * the wl_surface object.
++ * @section page_iface_wl_shell_surface_api API
++ * See @ref iface_wl_shell_surface.
++ */
++/**
++ * @defgroup iface_wl_shell_surface The wl_shell_surface interface
++ *
++ * An interface that may be implemented by a wl_surface, for
++ * implementations that provide a desktop-style user interface.
++ *
++ * It provides requests to treat surfaces like toplevel, fullscreen
++ * or popup windows, move, resize or maximize them, associate
++ * metadata like title and class, etc.
++ *
++ * On the server side the object is automatically destroyed when
++ * the related wl_surface is destroyed. On the client side,
++ * wl_shell_surface_destroy() must be called before destroying
++ * the wl_surface object.
++ */
++extern const struct wl_interface wl_shell_surface_interface;
++#endif
++#ifndef WL_SURFACE_INTERFACE
++#define WL_SURFACE_INTERFACE
++/**
++ * @page page_iface_wl_surface wl_surface
++ * @section page_iface_wl_surface_desc Description
++ *
++ * A surface is a rectangular area that is displayed on the screen.
++ * It has a location, size and pixel contents.
++ *
++ * The size of a surface (and relative positions on it) is described
++ * in surface-local coordinates, which may differ from the buffer
++ * coordinates of the pixel content, in case a buffer_transform
++ * or a buffer_scale is used.
++ *
++ * A surface without a "role" is fairly useless: a compositor does
++ * not know where, when or how to present it. The role is the
++ * purpose of a wl_surface. Examples of roles are a cursor for a
++ * pointer (as set by wl_pointer.set_cursor), a drag icon
++ * (wl_data_device.start_drag), a sub-surface
++ * (wl_subcompositor.get_subsurface), and a window as defined by a
++ * shell protocol (e.g. wl_shell.get_shell_surface).
++ *
++ * A surface can have only one role at a time. Initially a
++ * wl_surface does not have a role. Once a wl_surface is given a
++ * role, it is set permanently for the whole lifetime of the
++ * wl_surface object. Giving the current role again is allowed,
++ * unless explicitly forbidden by the relevant interface
++ * specification.
++ *
++ * Surface roles are given by requests in other interfaces such as
++ * wl_pointer.set_cursor. The request should explicitly mention
++ * that this request gives a role to a wl_surface. Often, this
++ * request also creates a new protocol object that represents the
++ * role and adds additional functionality to wl_surface. When a
++ * client wants to destroy a wl_surface, they must destroy this 'role
++ * object' before the wl_surface.
++ *
++ * Destroying the role object does not remove the role from the
++ * wl_surface, but it may stop the wl_surface from "playing the role".
++ * For instance, if a wl_subsurface object is destroyed, the wl_surface
++ * it was created for will be unmapped and forget its position and
++ * z-order. It is allowed to create a wl_subsurface for the same
++ * wl_surface again, but it is not allowed to use the wl_surface as
++ * a cursor (cursor is a different role than sub-surface, and role
++ * switching is not allowed).
++ * @section page_iface_wl_surface_api API
++ * See @ref iface_wl_surface.
++ */
++/**
++ * @defgroup iface_wl_surface The wl_surface interface
++ *
++ * A surface is a rectangular area that is displayed on the screen.
++ * It has a location, size and pixel contents.
++ *
++ * The size of a surface (and relative positions on it) is described
++ * in surface-local coordinates, which may differ from the buffer
++ * coordinates of the pixel content, in case a buffer_transform
++ * or a buffer_scale is used.
++ *
++ * A surface without a "role" is fairly useless: a compositor does
++ * not know where, when or how to present it. The role is the
++ * purpose of a wl_surface. Examples of roles are a cursor for a
++ * pointer (as set by wl_pointer.set_cursor), a drag icon
++ * (wl_data_device.start_drag), a sub-surface
++ * (wl_subcompositor.get_subsurface), and a window as defined by a
++ * shell protocol (e.g. wl_shell.get_shell_surface).
++ *
++ * A surface can have only one role at a time. Initially a
++ * wl_surface does not have a role. Once a wl_surface is given a
++ * role, it is set permanently for the whole lifetime of the
++ * wl_surface object. Giving the current role again is allowed,
++ * unless explicitly forbidden by the relevant interface
++ * specification.
++ *
++ * Surface roles are given by requests in other interfaces such as
++ * wl_pointer.set_cursor. The request should explicitly mention
++ * that this request gives a role to a wl_surface. Often, this
++ * request also creates a new protocol object that represents the
++ * role and adds additional functionality to wl_surface. When a
++ * client wants to destroy a wl_surface, they must destroy this 'role
++ * object' before the wl_surface.
++ *
++ * Destroying the role object does not remove the role from the
++ * wl_surface, but it may stop the wl_surface from "playing the role".
++ * For instance, if a wl_subsurface object is destroyed, the wl_surface
++ * it was created for will be unmapped and forget its position and
++ * z-order. It is allowed to create a wl_subsurface for the same
++ * wl_surface again, but it is not allowed to use the wl_surface as
++ * a cursor (cursor is a different role than sub-surface, and role
++ * switching is not allowed).
++ */
++extern const struct wl_interface wl_surface_interface;
++#endif
++#ifndef WL_SEAT_INTERFACE
++#define WL_SEAT_INTERFACE
++/**
++ * @page page_iface_wl_seat wl_seat
++ * @section page_iface_wl_seat_desc Description
++ *
++ * A seat is a group of keyboards, pointer and touch devices. This
++ * object is published as a global during start up, or when such a
++ * device is hot plugged. A seat typically has a pointer and
++ * maintains a keyboard focus and a pointer focus.
++ * @section page_iface_wl_seat_api API
++ * See @ref iface_wl_seat.
++ */
++/**
++ * @defgroup iface_wl_seat The wl_seat interface
++ *
++ * A seat is a group of keyboards, pointer and touch devices. This
++ * object is published as a global during start up, or when such a
++ * device is hot plugged. A seat typically has a pointer and
++ * maintains a keyboard focus and a pointer focus.
++ */
++extern const struct wl_interface wl_seat_interface;
++#endif
++#ifndef WL_POINTER_INTERFACE
++#define WL_POINTER_INTERFACE
++/**
++ * @page page_iface_wl_pointer wl_pointer
++ * @section page_iface_wl_pointer_desc Description
++ *
++ * The wl_pointer interface represents one or more input devices,
++ * such as mice, which control the pointer location and pointer_focus
++ * of a seat.
++ *
++ * The wl_pointer interface generates motion, enter and leave
++ * events for the surfaces that the pointer is located over,
++ * and button and axis events for button presses, button releases
++ * and scrolling.
++ * @section page_iface_wl_pointer_api API
++ * See @ref iface_wl_pointer.
++ */
++/**
++ * @defgroup iface_wl_pointer The wl_pointer interface
++ *
++ * The wl_pointer interface represents one or more input devices,
++ * such as mice, which control the pointer location and pointer_focus
++ * of a seat.
++ *
++ * The wl_pointer interface generates motion, enter and leave
++ * events for the surfaces that the pointer is located over,
++ * and button and axis events for button presses, button releases
++ * and scrolling.
++ */
++extern const struct wl_interface wl_pointer_interface;
++#endif
++#ifndef WL_KEYBOARD_INTERFACE
++#define WL_KEYBOARD_INTERFACE
++/**
++ * @page page_iface_wl_keyboard wl_keyboard
++ * @section page_iface_wl_keyboard_desc Description
++ *
++ * The wl_keyboard interface represents one or more keyboards
++ * associated with a seat.
++ * @section page_iface_wl_keyboard_api API
++ * See @ref iface_wl_keyboard.
++ */
++/**
++ * @defgroup iface_wl_keyboard The wl_keyboard interface
++ *
++ * The wl_keyboard interface represents one or more keyboards
++ * associated with a seat.
++ */
++extern const struct wl_interface wl_keyboard_interface;
++#endif
++#ifndef WL_TOUCH_INTERFACE
++#define WL_TOUCH_INTERFACE
++/**
++ * @page page_iface_wl_touch wl_touch
++ * @section page_iface_wl_touch_desc Description
++ *
++ * The wl_touch interface represents a touchscreen
++ * associated with a seat.
++ *
++ * Touch interactions can consist of one or more contacts.
++ * For each contact, a series of events is generated, starting
++ * with a down event, followed by zero or more motion events,
++ * and ending with an up event. Events relating to the same
++ * contact point can be identified by the ID of the sequence.
++ * @section page_iface_wl_touch_api API
++ * See @ref iface_wl_touch.
++ */
++/**
++ * @defgroup iface_wl_touch The wl_touch interface
++ *
++ * The wl_touch interface represents a touchscreen
++ * associated with a seat.
++ *
++ * Touch interactions can consist of one or more contacts.
++ * For each contact, a series of events is generated, starting
++ * with a down event, followed by zero or more motion events,
++ * and ending with an up event. Events relating to the same
++ * contact point can be identified by the ID of the sequence.
++ */
++extern const struct wl_interface wl_touch_interface;
++#endif
++#ifndef WL_OUTPUT_INTERFACE
++#define WL_OUTPUT_INTERFACE
++/**
++ * @page page_iface_wl_output wl_output
++ * @section page_iface_wl_output_desc Description
++ *
++ * An output describes part of the compositor geometry. The
++ * compositor works in the 'compositor coordinate system' and an
++ * output corresponds to a rectangular area in that space that is
++ * actually visible. This typically corresponds to a monitor that
++ * displays part of the compositor space. This object is published
++ * as global during start up, or when a monitor is hotplugged.
++ * @section page_iface_wl_output_api API
++ * See @ref iface_wl_output.
++ */
++/**
++ * @defgroup iface_wl_output The wl_output interface
++ *
++ * An output describes part of the compositor geometry. The
++ * compositor works in the 'compositor coordinate system' and an
++ * output corresponds to a rectangular area in that space that is
++ * actually visible. This typically corresponds to a monitor that
++ * displays part of the compositor space. This object is published
++ * as global during start up, or when a monitor is hotplugged.
++ */
++extern const struct wl_interface wl_output_interface;
++#endif
++#ifndef WL_REGION_INTERFACE
++#define WL_REGION_INTERFACE
++/**
++ * @page page_iface_wl_region wl_region
++ * @section page_iface_wl_region_desc Description
++ *
++ * A region object describes an area.
++ *
++ * Region objects are used to describe the opaque and input
++ * regions of a surface.
++ * @section page_iface_wl_region_api API
++ * See @ref iface_wl_region.
++ */
++/**
++ * @defgroup iface_wl_region The wl_region interface
++ *
++ * A region object describes an area.
++ *
++ * Region objects are used to describe the opaque and input
++ * regions of a surface.
++ */
++extern const struct wl_interface wl_region_interface;
++#endif
++#ifndef WL_SUBCOMPOSITOR_INTERFACE
++#define WL_SUBCOMPOSITOR_INTERFACE
++/**
++ * @page page_iface_wl_subcompositor wl_subcompositor
++ * @section page_iface_wl_subcompositor_desc Description
++ *
++ * The global interface exposing sub-surface compositing capabilities.
++ * A wl_surface, that has sub-surfaces associated, is called the
++ * parent surface. Sub-surfaces can be arbitrarily nested and create
++ * a tree of sub-surfaces.
++ *
++ * The root surface in a tree of sub-surfaces is the main
++ * surface. The main surface cannot be a sub-surface, because
++ * sub-surfaces must always have a parent.
++ *
++ * A main surface with its sub-surfaces forms a (compound) window.
++ * For window management purposes, this set of wl_surface objects is
++ * to be considered as a single window, and it should also behave as
++ * such.
++ *
++ * The aim of sub-surfaces is to offload some of the compositing work
++ * within a window from clients to the compositor. A prime example is
++ * a video player with decorations and video in separate wl_surface
++ * objects. This should allow the compositor to pass YUV video buffer
++ * processing to dedicated overlay hardware when possible.
++ * @section page_iface_wl_subcompositor_api API
++ * See @ref iface_wl_subcompositor.
++ */
++/**
++ * @defgroup iface_wl_subcompositor The wl_subcompositor interface
++ *
++ * The global interface exposing sub-surface compositing capabilities.
++ * A wl_surface, that has sub-surfaces associated, is called the
++ * parent surface. Sub-surfaces can be arbitrarily nested and create
++ * a tree of sub-surfaces.
++ *
++ * The root surface in a tree of sub-surfaces is the main
++ * surface. The main surface cannot be a sub-surface, because
++ * sub-surfaces must always have a parent.
++ *
++ * A main surface with its sub-surfaces forms a (compound) window.
++ * For window management purposes, this set of wl_surface objects is
++ * to be considered as a single window, and it should also behave as
++ * such.
++ *
++ * The aim of sub-surfaces is to offload some of the compositing work
++ * within a window from clients to the compositor. A prime example is
++ * a video player with decorations and video in separate wl_surface
++ * objects. This should allow the compositor to pass YUV video buffer
++ * processing to dedicated overlay hardware when possible.
++ */
++extern const struct wl_interface wl_subcompositor_interface;
++#endif
++#ifndef WL_SUBSURFACE_INTERFACE
++#define WL_SUBSURFACE_INTERFACE
++/**
++ * @page page_iface_wl_subsurface wl_subsurface
++ * @section page_iface_wl_subsurface_desc Description
++ *
++ * An additional interface to a wl_surface object, which has been
++ * made a sub-surface. A sub-surface has one parent surface. A
++ * sub-surface's size and position are not limited to that of the parent.
++ * Particularly, a sub-surface is not automatically clipped to its
++ * parent's area.
++ *
++ * A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
++ * and the parent surface is mapped. The order of which one happens
++ * first is irrelevant. A sub-surface is hidden if the parent becomes
++ * hidden, or if a NULL wl_buffer is applied. These rules apply
++ * recursively through the tree of surfaces.
++ *
++ * The behaviour of a wl_surface.commit request on a sub-surface
++ * depends on the sub-surface's mode. The possible modes are
++ * synchronized and desynchronized, see methods
++ * wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
++ * mode caches the wl_surface state to be applied when the parent's
++ * state gets applied, and desynchronized mode applies the pending
++ * wl_surface state directly. A sub-surface is initially in the
++ * synchronized mode.
++ *
++ * Sub-surfaces have also other kind of state, which is managed by
++ * wl_subsurface requests, as opposed to wl_surface requests. This
++ * state includes the sub-surface position relative to the parent
++ * surface (wl_subsurface.set_position), and the stacking order of
++ * the parent and its sub-surfaces (wl_subsurface.place_above and
++ * .place_below). This state is applied when the parent surface's
++ * wl_surface state is applied, regardless of the sub-surface's mode.
++ * As the exception, set_sync and set_desync are effective immediately.
++ *
++ * The main surface can be thought to be always in desynchronized mode,
++ * since it does not have a parent in the sub-surfaces sense.
++ *
++ * Even if a sub-surface is in desynchronized mode, it will behave as
++ * in synchronized mode, if its parent surface behaves as in
++ * synchronized mode. This rule is applied recursively throughout the
++ * tree of surfaces. This means, that one can set a sub-surface into
++ * synchronized mode, and then assume that all its child and grand-child
++ * sub-surfaces are synchronized, too, without explicitly setting them.
++ *
++ * If the wl_surface associated with the wl_subsurface is destroyed, the
++ * wl_subsurface object becomes inert. Note, that destroying either object
++ * takes effect immediately. If you need to synchronize the removal
++ * of a sub-surface to the parent surface update, unmap the sub-surface
++ * first by attaching a NULL wl_buffer, update parent, and then destroy
++ * the sub-surface.
++ *
++ * If the parent wl_surface object is destroyed, the sub-surface is
++ * unmapped.
++ * @section page_iface_wl_subsurface_api API
++ * See @ref iface_wl_subsurface.
++ */
++/**
++ * @defgroup iface_wl_subsurface The wl_subsurface interface
++ *
++ * An additional interface to a wl_surface object, which has been
++ * made a sub-surface. A sub-surface has one parent surface. A
++ * sub-surface's size and position are not limited to that of the parent.
++ * Particularly, a sub-surface is not automatically clipped to its
++ * parent's area.
++ *
++ * A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
++ * and the parent surface is mapped. The order of which one happens
++ * first is irrelevant. A sub-surface is hidden if the parent becomes
++ * hidden, or if a NULL wl_buffer is applied. These rules apply
++ * recursively through the tree of surfaces.
++ *
++ * The behaviour of a wl_surface.commit request on a sub-surface
++ * depends on the sub-surface's mode. The possible modes are
++ * synchronized and desynchronized, see methods
++ * wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
++ * mode caches the wl_surface state to be applied when the parent's
++ * state gets applied, and desynchronized mode applies the pending
++ * wl_surface state directly. A sub-surface is initially in the
++ * synchronized mode.
++ *
++ * Sub-surfaces have also other kind of state, which is managed by
++ * wl_subsurface requests, as opposed to wl_surface requests. This
++ * state includes the sub-surface position relative to the parent
++ * surface (wl_subsurface.set_position), and the stacking order of
++ * the parent and its sub-surfaces (wl_subsurface.place_above and
++ * .place_below). This state is applied when the parent surface's
++ * wl_surface state is applied, regardless of the sub-surface's mode.
++ * As the exception, set_sync and set_desync are effective immediately.
++ *
++ * The main surface can be thought to be always in desynchronized mode,
++ * since it does not have a parent in the sub-surfaces sense.
++ *
++ * Even if a sub-surface is in desynchronized mode, it will behave as
++ * in synchronized mode, if its parent surface behaves as in
++ * synchronized mode. This rule is applied recursively throughout the
++ * tree of surfaces. This means, that one can set a sub-surface into
++ * synchronized mode, and then assume that all its child and grand-child
++ * sub-surfaces are synchronized, too, without explicitly setting them.
++ *
++ * If the wl_surface associated with the wl_subsurface is destroyed, the
++ * wl_subsurface object becomes inert. Note, that destroying either object
++ * takes effect immediately. If you need to synchronize the removal
++ * of a sub-surface to the parent surface update, unmap the sub-surface
++ * first by attaching a NULL wl_buffer, update parent, and then destroy
++ * the sub-surface.
++ *
++ * If the parent wl_surface object is destroyed, the sub-surface is
++ * unmapped.
++ */
++extern const struct wl_interface wl_subsurface_interface;
++#endif
++
++#ifndef WL_DISPLAY_ERROR_ENUM
++#define WL_DISPLAY_ERROR_ENUM
++/**
++ * @ingroup iface_wl_display
++ * global error values
++ *
++ * These errors are global and can be emitted in response to any
++ * server request.
++ */
++enum wl_display_error {
++ /**
++ * server couldn't find object
++ */
++ WL_DISPLAY_ERROR_INVALID_OBJECT = 0,
++ /**
++ * method doesn't exist on the specified interface
++ */
++ WL_DISPLAY_ERROR_INVALID_METHOD = 1,
++ /**
++ * server is out of memory
++ */
++ WL_DISPLAY_ERROR_NO_MEMORY = 2,
++};
++#endif /* WL_DISPLAY_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_display
++ * @struct wl_display_listener
++ */
++struct wl_display_listener {
++ /**
++ * fatal error event
++ *
++ * The error event is sent out when a fatal (non-recoverable)
++ * error has occurred. The object_id argument is the object where
++ * the error occurred, most often in response to a request to that
++ * object. The code identifies the error and is defined by the
++ * object interface. As such, each interface defines its own set of
++ * error codes. The message is a brief description of the error,
++ * for (debugging) convenience.
++ * @param object_id object where the error occurred
++ * @param code error code
++ * @param message error description
++ */
++ void (*error)(void *data,
++ struct wl_display *wl_display,
++ void *object_id,
++ uint32_t code,
++ const char *message);
++ /**
++ * acknowledge object ID deletion
++ *
++ * This event is used internally by the object ID management
++ * logic. When a client deletes an object, the server will send
++ * this event to acknowledge that it has seen the delete request.
++ * When the client receives this event, it will know that it can
++ * safely reuse the object ID.
++ * @param id deleted object ID
++ */
++ void (*delete_id)(void *data,
++ struct wl_display *wl_display,
++ uint32_t id);
++};
++
++/**
++ * @ingroup iface_wl_display
++ */
++static inline int
++wl_display_add_listener(struct wl_display *wl_display,
++ const struct wl_display_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_display,
++ (void (**)(void)) listener, data);
++}
++
++#define WL_DISPLAY_SYNC 0
++#define WL_DISPLAY_GET_REGISTRY 1
++
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_ERROR_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_DELETE_ID_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_SYNC_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_GET_REGISTRY_SINCE_VERSION 1
++
++/** @ingroup iface_wl_display */
++static inline void
++wl_display_set_user_data(struct wl_display *wl_display, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_display, user_data);
++}
++
++/** @ingroup iface_wl_display */
++static inline void *
++wl_display_get_user_data(struct wl_display *wl_display)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_display);
++}
++
++static inline uint32_t
++wl_display_get_version(struct wl_display *wl_display)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_display);
++}
++
++/**
++ * @ingroup iface_wl_display
++ *
++ * The sync request asks the server to emit the 'done' event
++ * on the returned wl_callback object. Since requests are
++ * handled in-order and events are delivered in-order, this can
++ * be used as a barrier to ensure all previous requests and the
++ * resulting events have been handled.
++ *
++ * The object returned by this request will be destroyed by the
++ * compositor after the callback is fired and as such the client must not
++ * attempt to use it after that point.
++ *
++ * The callback_data passed in the callback is the event serial.
++ */
++static inline struct wl_callback *
++wl_display_sync(struct wl_display *wl_display)
++{
++ struct wl_proxy *callback;
++
++ callback = wl_proxy_marshal_flags((struct wl_proxy *) wl_display,
++ WL_DISPLAY_SYNC, &wl_callback_interface, wl_proxy_get_version((struct wl_proxy *) wl_display), 0, NULL);
++
++ return (struct wl_callback *) callback;
++}
++
++/**
++ * @ingroup iface_wl_display
++ *
++ * This request creates a registry object that allows the client
++ * to list and bind the global objects available from the
++ * compositor.
++ */
++static inline struct wl_registry *
++wl_display_get_registry(struct wl_display *wl_display)
++{
++ struct wl_proxy *registry;
++
++ registry = wl_proxy_marshal_flags((struct wl_proxy *) wl_display,
++ WL_DISPLAY_GET_REGISTRY, &wl_registry_interface, wl_proxy_get_version((struct wl_proxy *) wl_display), 0, NULL);
++
++ return (struct wl_registry *) registry;
++}
++
++/**
++ * @ingroup iface_wl_registry
++ * @struct wl_registry_listener
++ */
++struct wl_registry_listener {
++ /**
++ * announce global object
++ *
++ * Notify the client of global objects.
++ *
++ * The event notifies the client that a global object with the
++ * given name is now available, and it implements the given version
++ * of the given interface.
++ * @param name numeric name of the global object
++ * @param interface interface implemented by the object
++ * @param version interface version
++ */
++ void (*global)(void *data,
++ struct wl_registry *wl_registry,
++ uint32_t name,
++ const char *interface,
++ uint32_t version);
++ /**
++ * announce removal of global object
++ *
++ * Notify the client of removed global objects.
++ *
++ * This event notifies the client that the global identified by
++ * name is no longer available. If the client bound to the global
++ * using the bind request, the client should now destroy that
++ * object.
++ *
++ * The object remains valid and requests to the object will be
++ * ignored until the client destroys it, to avoid races between the
++ * global going away and a client sending a request to it.
++ * @param name numeric name of the global object
++ */
++ void (*global_remove)(void *data,
++ struct wl_registry *wl_registry,
++ uint32_t name);
++};
++
++/**
++ * @ingroup iface_wl_registry
++ */
++static inline int
++wl_registry_add_listener(struct wl_registry *wl_registry,
++ const struct wl_registry_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_registry,
++ (void (**)(void)) listener, data);
++}
++
++#define WL_REGISTRY_BIND 0
++
++/**
++ * @ingroup iface_wl_registry
++ */
++#define WL_REGISTRY_GLOBAL_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_registry
++ */
++#define WL_REGISTRY_GLOBAL_REMOVE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_registry
++ */
++#define WL_REGISTRY_BIND_SINCE_VERSION 1
++
++/** @ingroup iface_wl_registry */
++static inline void
++wl_registry_set_user_data(struct wl_registry *wl_registry, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_registry, user_data);
++}
++
++/** @ingroup iface_wl_registry */
++static inline void *
++wl_registry_get_user_data(struct wl_registry *wl_registry)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_registry);
++}
++
++static inline uint32_t
++wl_registry_get_version(struct wl_registry *wl_registry)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_registry);
++}
++
++/** @ingroup iface_wl_registry */
++static inline void
++wl_registry_destroy(struct wl_registry *wl_registry)
++{
++ wl_proxy_destroy((struct wl_proxy *) wl_registry);
++}
++
++/**
++ * @ingroup iface_wl_registry
++ *
++ * Binds a new, client-created object to the server using the
++ * specified name as the identifier.
++ */
++static inline void *
++wl_registry_bind(struct wl_registry *wl_registry, uint32_t name, const struct wl_interface *interface, uint32_t version)
++{
++ struct wl_proxy *id;
++
++ id = wl_proxy_marshal_flags((struct wl_proxy *) wl_registry,
++ WL_REGISTRY_BIND, interface, version, 0, name, interface->name, version, NULL);
++
++ return (void *) id;
++}
++
++/**
++ * @ingroup iface_wl_callback
++ * @struct wl_callback_listener
++ */
++struct wl_callback_listener {
++ /**
++ * done event
++ *
++ * Notify the client when the related request is done.
++ * @param callback_data request-specific data for the callback
++ */
++ void (*done)(void *data,
++ struct wl_callback *wl_callback,
++ uint32_t callback_data);
++};
++
++/**
++ * @ingroup iface_wl_callback
++ */
++static inline int
++wl_callback_add_listener(struct wl_callback *wl_callback,
++ const struct wl_callback_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_callback,
++ (void (**)(void)) listener, data);
++}
++
++/**
++ * @ingroup iface_wl_callback
++ */
++#define WL_CALLBACK_DONE_SINCE_VERSION 1
++
++
++/** @ingroup iface_wl_callback */
++static inline void
++wl_callback_set_user_data(struct wl_callback *wl_callback, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_callback, user_data);
++}
++
++/** @ingroup iface_wl_callback */
++static inline void *
++wl_callback_get_user_data(struct wl_callback *wl_callback)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_callback);
++}
++
++static inline uint32_t
++wl_callback_get_version(struct wl_callback *wl_callback)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_callback);
++}
++
++/** @ingroup iface_wl_callback */
++static inline void
++wl_callback_destroy(struct wl_callback *wl_callback)
++{
++ wl_proxy_destroy((struct wl_proxy *) wl_callback);
++}
++
++#define WL_COMPOSITOR_CREATE_SURFACE 0
++#define WL_COMPOSITOR_CREATE_REGION 1
++
++
++/**
++ * @ingroup iface_wl_compositor
++ */
++#define WL_COMPOSITOR_CREATE_SURFACE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_compositor
++ */
++#define WL_COMPOSITOR_CREATE_REGION_SINCE_VERSION 1
++
++/** @ingroup iface_wl_compositor */
++static inline void
++wl_compositor_set_user_data(struct wl_compositor *wl_compositor, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_compositor, user_data);
++}
++
++/** @ingroup iface_wl_compositor */
++static inline void *
++wl_compositor_get_user_data(struct wl_compositor *wl_compositor)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_compositor);
++}
++
++static inline uint32_t
++wl_compositor_get_version(struct wl_compositor *wl_compositor)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_compositor);
++}
++
++/** @ingroup iface_wl_compositor */
++static inline void
++wl_compositor_destroy(struct wl_compositor *wl_compositor)
++{
++ wl_proxy_destroy((struct wl_proxy *) wl_compositor);
++}
++
++/**
++ * @ingroup iface_wl_compositor
++ *
++ * Ask the compositor to create a new surface.
++ */
++static inline struct wl_surface *
++wl_compositor_create_surface(struct wl_compositor *wl_compositor)
++{
++ struct wl_proxy *id;
++
++ id = wl_proxy_marshal_flags((struct wl_proxy *) wl_compositor,
++ WL_COMPOSITOR_CREATE_SURFACE, &wl_surface_interface, wl_proxy_get_version((struct wl_proxy *) wl_compositor), 0, NULL);
++
++ return (struct wl_surface *) id;
++}
++
++/**
++ * @ingroup iface_wl_compositor
++ *
++ * Ask the compositor to create a new region.
++ */
++static inline struct wl_region *
++wl_compositor_create_region(struct wl_compositor *wl_compositor)
++{
++ struct wl_proxy *id;
++
++ id = wl_proxy_marshal_flags((struct wl_proxy *) wl_compositor,
++ WL_COMPOSITOR_CREATE_REGION, &wl_region_interface, wl_proxy_get_version((struct wl_proxy *) wl_compositor), 0, NULL);
++
++ return (struct wl_region *) id;
++}
++
++#define WL_SHM_POOL_CREATE_BUFFER 0
++#define WL_SHM_POOL_DESTROY 1
++#define WL_SHM_POOL_RESIZE 2
++
++
++/**
++ * @ingroup iface_wl_shm_pool
++ */
++#define WL_SHM_POOL_CREATE_BUFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shm_pool
++ */
++#define WL_SHM_POOL_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shm_pool
++ */
++#define WL_SHM_POOL_RESIZE_SINCE_VERSION 1
++
++/** @ingroup iface_wl_shm_pool */
++static inline void
++wl_shm_pool_set_user_data(struct wl_shm_pool *wl_shm_pool, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_shm_pool, user_data);
++}
++
++/** @ingroup iface_wl_shm_pool */
++static inline void *
++wl_shm_pool_get_user_data(struct wl_shm_pool *wl_shm_pool)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_shm_pool);
++}
++
++static inline uint32_t
++wl_shm_pool_get_version(struct wl_shm_pool *wl_shm_pool)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_shm_pool);
++}
++
++/**
++ * @ingroup iface_wl_shm_pool
++ *
++ * Create a wl_buffer object from the pool.
++ *
++ * The buffer is created offset bytes into the pool and has
++ * width and height as specified. The stride argument specifies
++ * the number of bytes from the beginning of one row to the beginning
++ * of the next. The format is the pixel format of the buffer and
++ * must be one of those advertised through the wl_shm.format event.
++ *
++ * A buffer will keep a reference to the pool it was created from
++ * so it is valid to destroy the pool immediately after creating
++ * a buffer from it.
++ */
++static inline struct wl_buffer *
++wl_shm_pool_create_buffer(struct wl_shm_pool *wl_shm_pool, int32_t offset, int32_t width, int32_t height, int32_t stride, uint32_t format)
++{
++ struct wl_proxy *id;
++
++ id = wl_proxy_marshal_flags((struct wl_proxy *) wl_shm_pool,
++ WL_SHM_POOL_CREATE_BUFFER, &wl_buffer_interface, wl_proxy_get_version((struct wl_proxy *) wl_shm_pool), 0, NULL, offset, width, height, stride, format);
++
++ return (struct wl_buffer *) id;
++}
++
++/**
++ * @ingroup iface_wl_shm_pool
++ *
++ * Destroy the shared memory pool.
++ *
++ * The mmapped memory will be released when all
++ * buffers that have been created from this pool
++ * are gone.
++ */
++static inline void
++wl_shm_pool_destroy(struct wl_shm_pool *wl_shm_pool)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_shm_pool,
++ WL_SHM_POOL_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shm_pool), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_shm_pool
++ *
++ * This request will cause the server to remap the backing memory
++ * for the pool from the file descriptor passed when the pool was
++ * created, but using the new size. This request can only be
++ * used to make the pool bigger.
++ */
++static inline void
++wl_shm_pool_resize(struct wl_shm_pool *wl_shm_pool, int32_t size)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_shm_pool,
++ WL_SHM_POOL_RESIZE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shm_pool), 0, size);
++}
++
++#ifndef WL_SHM_ERROR_ENUM
++#define WL_SHM_ERROR_ENUM
++/**
++ * @ingroup iface_wl_shm
++ * wl_shm error values
++ *
++ * These errors can be emitted in response to wl_shm requests.
++ */
++enum wl_shm_error {
++ /**
++ * buffer format is not known
++ */
++ WL_SHM_ERROR_INVALID_FORMAT = 0,
++ /**
++ * invalid size or stride during pool or buffer creation
++ */
++ WL_SHM_ERROR_INVALID_STRIDE = 1,
++ /**
++ * mmapping the file descriptor failed
++ */
++ WL_SHM_ERROR_INVALID_FD = 2,
++};
++#endif /* WL_SHM_ERROR_ENUM */
++
++#ifndef WL_SHM_FORMAT_ENUM
++#define WL_SHM_FORMAT_ENUM
++/**
++ * @ingroup iface_wl_shm
++ * pixel formats
++ *
++ * This describes the memory layout of an individual pixel.
++ *
++ * All renderers should support argb8888 and xrgb8888 but any other
++ * formats are optional and may not be supported by the particular
++ * renderer in use.
++ *
++ * The drm format codes match the macros defined in drm_fourcc.h.
++ * The formats actually supported by the compositor will be
++ * reported by the format event.
++ */
++enum wl_shm_format {
++ /**
++ * 32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_ARGB8888 = 0,
++ /**
++ * 32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_XRGB8888 = 1,
++ /**
++ * 8-bit color index format, [7:0] C
++ */
++ WL_SHM_FORMAT_C8 = 0x20203843,
++ /**
++ * 8-bit RGB format, [7:0] R:G:B 3:3:2
++ */
++ WL_SHM_FORMAT_RGB332 = 0x38424752,
++ /**
++ * 8-bit BGR format, [7:0] B:G:R 2:3:3
++ */
++ WL_SHM_FORMAT_BGR233 = 0x38524742,
++ /**
++ * 16-bit xRGB format, [15:0] x:R:G:B 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_XRGB4444 = 0x32315258,
++ /**
++ * 16-bit xBGR format, [15:0] x:B:G:R 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_XBGR4444 = 0x32314258,
++ /**
++ * 16-bit RGBx format, [15:0] R:G:B:x 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_RGBX4444 = 0x32315852,
++ /**
++ * 16-bit BGRx format, [15:0] B:G:R:x 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_BGRX4444 = 0x32315842,
++ /**
++ * 16-bit ARGB format, [15:0] A:R:G:B 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_ARGB4444 = 0x32315241,
++ /**
++ * 16-bit ABGR format, [15:0] A:B:G:R 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_ABGR4444 = 0x32314241,
++ /**
++ * 16-bit RBGA format, [15:0] R:G:B:A 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_RGBA4444 = 0x32314152,
++ /**
++ * 16-bit BGRA format, [15:0] B:G:R:A 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_BGRA4444 = 0x32314142,
++ /**
++ * 16-bit xRGB format, [15:0] x:R:G:B 1:5:5:5 little endian
++ */
++ WL_SHM_FORMAT_XRGB1555 = 0x35315258,
++ /**
++ * 16-bit xBGR 1555 format, [15:0] x:B:G:R 1:5:5:5 little endian
++ */
++ WL_SHM_FORMAT_XBGR1555 = 0x35314258,
++ /**
++ * 16-bit RGBx 5551 format, [15:0] R:G:B:x 5:5:5:1 little endian
++ */
++ WL_SHM_FORMAT_RGBX5551 = 0x35315852,
++ /**
++ * 16-bit BGRx 5551 format, [15:0] B:G:R:x 5:5:5:1 little endian
++ */
++ WL_SHM_FORMAT_BGRX5551 = 0x35315842,
++ /**
++ * 16-bit ARGB 1555 format, [15:0] A:R:G:B 1:5:5:5 little endian
++ */
++ WL_SHM_FORMAT_ARGB1555 = 0x35315241,
++ /**
++ * 16-bit ABGR 1555 format, [15:0] A:B:G:R 1:5:5:5 little endian
++ */
++ WL_SHM_FORMAT_ABGR1555 = 0x35314241,
++ /**
++ * 16-bit RGBA 5551 format, [15:0] R:G:B:A 5:5:5:1 little endian
++ */
++ WL_SHM_FORMAT_RGBA5551 = 0x35314152,
++ /**
++ * 16-bit BGRA 5551 format, [15:0] B:G:R:A 5:5:5:1 little endian
++ */
++ WL_SHM_FORMAT_BGRA5551 = 0x35314142,
++ /**
++ * 16-bit RGB 565 format, [15:0] R:G:B 5:6:5 little endian
++ */
++ WL_SHM_FORMAT_RGB565 = 0x36314752,
++ /**
++ * 16-bit BGR 565 format, [15:0] B:G:R 5:6:5 little endian
++ */
++ WL_SHM_FORMAT_BGR565 = 0x36314742,
++ /**
++ * 24-bit RGB format, [23:0] R:G:B little endian
++ */
++ WL_SHM_FORMAT_RGB888 = 0x34324752,
++ /**
++ * 24-bit BGR format, [23:0] B:G:R little endian
++ */
++ WL_SHM_FORMAT_BGR888 = 0x34324742,
++ /**
++ * 32-bit xBGR format, [31:0] x:B:G:R 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_XBGR8888 = 0x34324258,
++ /**
++ * 32-bit RGBx format, [31:0] R:G:B:x 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_RGBX8888 = 0x34325852,
++ /**
++ * 32-bit BGRx format, [31:0] B:G:R:x 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_BGRX8888 = 0x34325842,
++ /**
++ * 32-bit ABGR format, [31:0] A:B:G:R 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_ABGR8888 = 0x34324241,
++ /**
++ * 32-bit RGBA format, [31:0] R:G:B:A 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_RGBA8888 = 0x34324152,
++ /**
++ * 32-bit BGRA format, [31:0] B:G:R:A 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_BGRA8888 = 0x34324142,
++ /**
++ * 32-bit xRGB format, [31:0] x:R:G:B 2:10:10:10 little endian
++ */
++ WL_SHM_FORMAT_XRGB2101010 = 0x30335258,
++ /**
++ * 32-bit xBGR format, [31:0] x:B:G:R 2:10:10:10 little endian
++ */
++ WL_SHM_FORMAT_XBGR2101010 = 0x30334258,
++ /**
++ * 32-bit RGBx format, [31:0] R:G:B:x 10:10:10:2 little endian
++ */
++ WL_SHM_FORMAT_RGBX1010102 = 0x30335852,
++ /**
++ * 32-bit BGRx format, [31:0] B:G:R:x 10:10:10:2 little endian
++ */
++ WL_SHM_FORMAT_BGRX1010102 = 0x30335842,
++ /**
++ * 32-bit ARGB format, [31:0] A:R:G:B 2:10:10:10 little endian
++ */
++ WL_SHM_FORMAT_ARGB2101010 = 0x30335241,
++ /**
++ * 32-bit ABGR format, [31:0] A:B:G:R 2:10:10:10 little endian
++ */
++ WL_SHM_FORMAT_ABGR2101010 = 0x30334241,
++ /**
++ * 32-bit RGBA format, [31:0] R:G:B:A 10:10:10:2 little endian
++ */
++ WL_SHM_FORMAT_RGBA1010102 = 0x30334152,
++ /**
++ * 32-bit BGRA format, [31:0] B:G:R:A 10:10:10:2 little endian
++ */
++ WL_SHM_FORMAT_BGRA1010102 = 0x30334142,
++ /**
++ * packed YCbCr format, [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_YUYV = 0x56595559,
++ /**
++ * packed YCbCr format, [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_YVYU = 0x55595659,
++ /**
++ * packed YCbCr format, [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_UYVY = 0x59565955,
++ /**
++ * packed YCbCr format, [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_VYUY = 0x59555956,
++ /**
++ * packed AYCbCr format, [31:0] A:Y:Cb:Cr 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_AYUV = 0x56555941,
++ /**
++ * 2 plane YCbCr Cr:Cb format, 2x2 subsampled Cr:Cb plane
++ */
++ WL_SHM_FORMAT_NV12 = 0x3231564e,
++ /**
++ * 2 plane YCbCr Cb:Cr format, 2x2 subsampled Cb:Cr plane
++ */
++ WL_SHM_FORMAT_NV21 = 0x3132564e,
++ /**
++ * 2 plane YCbCr Cr:Cb format, 2x1 subsampled Cr:Cb plane
++ */
++ WL_SHM_FORMAT_NV16 = 0x3631564e,
++ /**
++ * 2 plane YCbCr Cb:Cr format, 2x1 subsampled Cb:Cr plane
++ */
++ WL_SHM_FORMAT_NV61 = 0x3136564e,
++ /**
++ * 3 plane YCbCr format, 4x4 subsampled Cb (1) and Cr (2) planes
++ */
++ WL_SHM_FORMAT_YUV410 = 0x39565559,
++ /**
++ * 3 plane YCbCr format, 4x4 subsampled Cr (1) and Cb (2) planes
++ */
++ WL_SHM_FORMAT_YVU410 = 0x39555659,
++ /**
++ * 3 plane YCbCr format, 4x1 subsampled Cb (1) and Cr (2) planes
++ */
++ WL_SHM_FORMAT_YUV411 = 0x31315559,
++ /**
++ * 3 plane YCbCr format, 4x1 subsampled Cr (1) and Cb (2) planes
++ */
++ WL_SHM_FORMAT_YVU411 = 0x31315659,
++ /**
++ * 3 plane YCbCr format, 2x2 subsampled Cb (1) and Cr (2) planes
++ */
++ WL_SHM_FORMAT_YUV420 = 0x32315559,
++ /**
++ * 3 plane YCbCr format, 2x2 subsampled Cr (1) and Cb (2) planes
++ */
++ WL_SHM_FORMAT_YVU420 = 0x32315659,
++ /**
++ * 3 plane YCbCr format, 2x1 subsampled Cb (1) and Cr (2) planes
++ */
++ WL_SHM_FORMAT_YUV422 = 0x36315559,
++ /**
++ * 3 plane YCbCr format, 2x1 subsampled Cr (1) and Cb (2) planes
++ */
++ WL_SHM_FORMAT_YVU422 = 0x36315659,
++ /**
++ * 3 plane YCbCr format, non-subsampled Cb (1) and Cr (2) planes
++ */
++ WL_SHM_FORMAT_YUV444 = 0x34325559,
++ /**
++ * 3 plane YCbCr format, non-subsampled Cr (1) and Cb (2) planes
++ */
++ WL_SHM_FORMAT_YVU444 = 0x34325659,
++};
++#endif /* WL_SHM_FORMAT_ENUM */
++
++/**
++ * @ingroup iface_wl_shm
++ * @struct wl_shm_listener
++ */
++struct wl_shm_listener {
++ /**
++ * pixel format description
++ *
++ * Informs the client about a valid pixel format that can be used
++ * for buffers. Known formats include argb8888 and xrgb8888.
++ * @param format buffer pixel format
++ */
++ void (*format)(void *data,
++ struct wl_shm *wl_shm,
++ uint32_t format);
++};
++
++/**
++ * @ingroup iface_wl_shm
++ */
++static inline int
++wl_shm_add_listener(struct wl_shm *wl_shm,
++ const struct wl_shm_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_shm,
++ (void (**)(void)) listener, data);
++}
++
++#define WL_SHM_CREATE_POOL 0
++
++/**
++ * @ingroup iface_wl_shm
++ */
++#define WL_SHM_FORMAT_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_shm
++ */
++#define WL_SHM_CREATE_POOL_SINCE_VERSION 1
++
++/** @ingroup iface_wl_shm */
++static inline void
++wl_shm_set_user_data(struct wl_shm *wl_shm, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_shm, user_data);
++}
++
++/** @ingroup iface_wl_shm */
++static inline void *
++wl_shm_get_user_data(struct wl_shm *wl_shm)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_shm);
++}
++
++static inline uint32_t
++wl_shm_get_version(struct wl_shm *wl_shm)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_shm);
++}
++
++/** @ingroup iface_wl_shm */
++static inline void
++wl_shm_destroy(struct wl_shm *wl_shm)
++{
++ wl_proxy_destroy((struct wl_proxy *) wl_shm);
++}
++
++/**
++ * @ingroup iface_wl_shm
++ *
++ * Create a new wl_shm_pool object.
++ *
++ * The pool can be used to create shared memory based buffer
++ * objects. The server will mmap size bytes of the passed file
++ * descriptor, to use as backing memory for the pool.
++ */
++static inline struct wl_shm_pool *
++wl_shm_create_pool(struct wl_shm *wl_shm, int32_t fd, int32_t size)
++{
++ struct wl_proxy *id;
++
++ id = wl_proxy_marshal_flags((struct wl_proxy *) wl_shm,
++ WL_SHM_CREATE_POOL, &wl_shm_pool_interface, wl_proxy_get_version((struct wl_proxy *) wl_shm), 0, NULL, fd, size);
++
++ return (struct wl_shm_pool *) id;
++}
++
++/**
++ * @ingroup iface_wl_buffer
++ * @struct wl_buffer_listener
++ */
++struct wl_buffer_listener {
++ /**
++ * compositor releases buffer
++ *
++ * Sent when this wl_buffer is no longer used by the compositor.
++ * The client is now free to reuse or destroy this buffer and its
++ * backing storage.
++ *
++ * If a client receives a release event before the frame callback
++ * requested in the same wl_surface.commit that attaches this
++ * wl_buffer to a surface, then the client is immediately free to
++ * reuse the buffer and its backing storage, and does not need a
++ * second buffer for the next surface content update. Typically
++ * this is possible, when the compositor maintains a copy of the
++ * wl_surface contents, e.g. as a GL texture. This is an important
++ * optimization for GL(ES) compositors with wl_shm clients.
++ */
++ void (*release)(void *data,
++ struct wl_buffer *wl_buffer);
++};
++
++/**
++ * @ingroup iface_wl_buffer
++ */
++static inline int
++wl_buffer_add_listener(struct wl_buffer *wl_buffer,
++ const struct wl_buffer_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_buffer,
++ (void (**)(void)) listener, data);
++}
++
++#define WL_BUFFER_DESTROY 0
++
++/**
++ * @ingroup iface_wl_buffer
++ */
++#define WL_BUFFER_RELEASE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_buffer
++ */
++#define WL_BUFFER_DESTROY_SINCE_VERSION 1
++
++/** @ingroup iface_wl_buffer */
++static inline void
++wl_buffer_set_user_data(struct wl_buffer *wl_buffer, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_buffer, user_data);
++}
++
++/** @ingroup iface_wl_buffer */
++static inline void *
++wl_buffer_get_user_data(struct wl_buffer *wl_buffer)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_buffer);
++}
++
++static inline uint32_t
++wl_buffer_get_version(struct wl_buffer *wl_buffer)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_buffer);
++}
++
++/**
++ * @ingroup iface_wl_buffer
++ *
++ * Destroy a buffer. If and how you need to release the backing
++ * storage is defined by the buffer factory interface.
++ *
++ * For possible side-effects to a surface, see wl_surface.attach.
++ */
++static inline void
++wl_buffer_destroy(struct wl_buffer *wl_buffer)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_buffer,
++ WL_BUFFER_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_buffer), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#ifndef WL_DATA_OFFER_ERROR_ENUM
++#define WL_DATA_OFFER_ERROR_ENUM
++enum wl_data_offer_error {
++ /**
++ * finish request was called untimely
++ */
++ WL_DATA_OFFER_ERROR_INVALID_FINISH = 0,
++ /**
++ * action mask contains invalid values
++ */
++ WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK = 1,
++ /**
++ * action argument has an invalid value
++ */
++ WL_DATA_OFFER_ERROR_INVALID_ACTION = 2,
++ /**
++ * offer doesn't accept this request
++ */
++ WL_DATA_OFFER_ERROR_INVALID_OFFER = 3,
++};
++#endif /* WL_DATA_OFFER_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_data_offer
++ * @struct wl_data_offer_listener
++ */
++struct wl_data_offer_listener {
++ /**
++ * advertise offered mime type
++ *
++ * Sent immediately after creating the wl_data_offer object. One
++ * event per offered mime type.
++ * @param mime_type offered mime type
++ */
++ void (*offer)(void *data,
++ struct wl_data_offer *wl_data_offer,
++ const char *mime_type);
++ /**
++ * notify the source-side available actions
++ *
++ * This event indicates the actions offered by the data source.
++ * It will be sent right after wl_data_device.enter, or anytime the
++ * source side changes its offered actions through
++ * wl_data_source.set_actions.
++ * @param source_actions actions offered by the data source
++ * @since 3
++ */
++ void (*source_actions)(void *data,
++ struct wl_data_offer *wl_data_offer,
++ uint32_t source_actions);
++ /**
++ * notify the selected action
++ *
++ * This event indicates the action selected by the compositor
++ * after matching the source/destination side actions. Only one
++ * action (or none) will be offered here.
++ *
++ * This event can be emitted multiple times during the
++ * drag-and-drop operation in response to destination side action
++ * changes through wl_data_offer.set_actions.
++ *
++ * This event will no longer be emitted after wl_data_device.drop
++ * happened on the drag-and-drop destination, the client must honor
++ * the last action received, or the last preferred one set through
++ * wl_data_offer.set_actions when handling an "ask" action.
++ *
++ * Compositors may also change the selected action on the fly,
++ * mainly in response to keyboard modifier changes during the
++ * drag-and-drop operation.
++ *
++ * The most recent action received is always the valid one. Prior
++ * to receiving wl_data_device.drop, the chosen action may change
++ * (e.g. due to keyboard modifiers being pressed). At the time of
++ * receiving wl_data_device.drop the drag-and-drop destination must
++ * honor the last action received.
++ *
++ * Action changes may still happen after wl_data_device.drop,
++ * especially on "ask" actions, where the drag-and-drop destination
++ * may choose another action afterwards. Action changes happening
++ * at this stage are always the result of inter-client negotiation,
++ * the compositor shall no longer be able to induce a different
++ * action.
++ *
++ * Upon "ask" actions, it is expected that the drag-and-drop
++ * destination may potentially choose a different action and/or
++ * mime type, based on wl_data_offer.source_actions and finally
++ * chosen by the user (e.g. popping up a menu with the available
++ * options). The final wl_data_offer.set_actions and
++ * wl_data_offer.accept requests must happen before the call to
++ * wl_data_offer.finish.
++ * @param dnd_action action selected by the compositor
++ * @since 3
++ */
++ void (*action)(void *data,
++ struct wl_data_offer *wl_data_offer,
++ uint32_t dnd_action);
++};
++
++/**
++ * @ingroup iface_wl_data_offer
++ */
++static inline int
++wl_data_offer_add_listener(struct wl_data_offer *wl_data_offer,
++ const struct wl_data_offer_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_data_offer,
++ (void (**)(void)) listener, data);
++}
++
++#define WL_DATA_OFFER_ACCEPT 0
++#define WL_DATA_OFFER_RECEIVE 1
++#define WL_DATA_OFFER_DESTROY 2
++#define WL_DATA_OFFER_FINISH 3
++#define WL_DATA_OFFER_SET_ACTIONS 4
++
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_OFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_ACTION_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_ACCEPT_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_RECEIVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_FINISH_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION 3
++
++/** @ingroup iface_wl_data_offer */
++static inline void
++wl_data_offer_set_user_data(struct wl_data_offer *wl_data_offer, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_data_offer, user_data);
++}
++
++/** @ingroup iface_wl_data_offer */
++static inline void *
++wl_data_offer_get_user_data(struct wl_data_offer *wl_data_offer)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_data_offer);
++}
++
++static inline uint32_t
++wl_data_offer_get_version(struct wl_data_offer *wl_data_offer)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_data_offer);
++}
++
++/**
++ * @ingroup iface_wl_data_offer
++ *
++ * Indicate that the client can accept the given mime type, or
++ * NULL for not accepted.
++ *
++ * For objects of version 2 or older, this request is used by the
++ * client to give feedback whether the client can receive the given
++ * mime type, or NULL if none is accepted; the feedback does not
++ * determine whether the drag-and-drop operation succeeds or not.
++ *
++ * For objects of version 3 or newer, this request determines the
++ * final result of the drag-and-drop operation. If the end result
++ * is that no mime types were accepted, the drag-and-drop operation
++ * will be cancelled and the corresponding drag source will receive
++ * wl_data_source.cancelled. Clients may still use this event in
++ * conjunction with wl_data_source.action for feedback.
++ */
++static inline void
++wl_data_offer_accept(struct wl_data_offer *wl_data_offer, uint32_t serial, const char *mime_type)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer,
++ WL_DATA_OFFER_ACCEPT, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), 0, serial, mime_type);
++}
++
++/**
++ * @ingroup iface_wl_data_offer
++ *
++ * To transfer the offered data, the client issues this request
++ * and indicates the mime type it wants to receive. The transfer
++ * happens through the passed file descriptor (typically created
++ * with the pipe system call). The source client writes the data
++ * in the mime type representation requested and then closes the
++ * file descriptor.
++ *
++ * The receiving client reads from the read end of the pipe until
++ * EOF and then closes its end, at which point the transfer is
++ * complete.
++ *
++ * This request may happen multiple times for different mime types,
++ * both before and after wl_data_device.drop. Drag-and-drop destination
++ * clients may preemptively fetch data or examine it more closely to
++ * determine acceptance.
++ */
++static inline void
++wl_data_offer_receive(struct wl_data_offer *wl_data_offer, const char *mime_type, int32_t fd)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer,
++ WL_DATA_OFFER_RECEIVE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), 0, mime_type, fd);
++}
++
++/**
++ * @ingroup iface_wl_data_offer
++ *
++ * Destroy the data offer.
++ */
++static inline void
++wl_data_offer_destroy(struct wl_data_offer *wl_data_offer)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer,
++ WL_DATA_OFFER_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_data_offer
++ *
++ * Notifies the compositor that the drag destination successfully
++ * finished the drag-and-drop operation.
++ *
++ * Upon receiving this request, the compositor will emit
++ * wl_data_source.dnd_finished on the drag source client.
++ *
++ * It is a client error to perform other requests than
++ * wl_data_offer.destroy after this one. It is also an error to perform
++ * this request after a NULL mime type has been set in
++ * wl_data_offer.accept or no action was received through
++ * wl_data_offer.action.
++ */
++static inline void
++wl_data_offer_finish(struct wl_data_offer *wl_data_offer)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer,
++ WL_DATA_OFFER_FINISH, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), 0);
++}
++
++/**
++ * @ingroup iface_wl_data_offer
++ *
++ * Sets the actions that the destination side client supports for
++ * this operation. This request may trigger the emission of
++ * wl_data_source.action and wl_data_offer.action events if the compositor
++ * needs to change the selected action.
++ *
++ * This request can be called multiple times throughout the
++ * drag-and-drop operation, typically in response to wl_data_device.enter
++ * or wl_data_device.motion events.
++ *
++ * This request determines the final result of the drag-and-drop
++ * operation. If the end result is that no action is accepted,
++ * the drag source will receive wl_drag_source.cancelled.
++ *
++ * The dnd_actions argument must contain only values expressed in the
++ * wl_data_device_manager.dnd_actions enum, and the preferred_action
++ * argument must only contain one of those values set, otherwise it
++ * will result in a protocol error.
++ *
++ * While managing an "ask" action, the destination drag-and-drop client
++ * may perform further wl_data_offer.receive requests, and is expected
++ * to perform one last wl_data_offer.set_actions request with a preferred
++ * action other than "ask" (and optionally wl_data_offer.accept) before
++ * requesting wl_data_offer.finish, in order to convey the action selected
++ * by the user. If the preferred action is not in the
++ * wl_data_offer.source_actions mask, an error will be raised.
++ *
++ * If the "ask" action is dismissed (e.g. user cancellation), the client
++ * is expected to perform wl_data_offer.destroy right away.
++ *
++ * This request can only be made on drag-and-drop offers, a protocol error
++ * will be raised otherwise.
++ */
++static inline void
++wl_data_offer_set_actions(struct wl_data_offer *wl_data_offer, uint32_t dnd_actions, uint32_t preferred_action)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer,
++ WL_DATA_OFFER_SET_ACTIONS, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), 0, dnd_actions, preferred_action);
++}
++
++#ifndef WL_DATA_SOURCE_ERROR_ENUM
++#define WL_DATA_SOURCE_ERROR_ENUM
++enum wl_data_source_error {
++ /**
++ * action mask contains invalid values
++ */
++ WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK = 0,
++ /**
++ * source doesn't accept this request
++ */
++ WL_DATA_SOURCE_ERROR_INVALID_SOURCE = 1,
++};
++#endif /* WL_DATA_SOURCE_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_data_source
++ * @struct wl_data_source_listener
++ */
++struct wl_data_source_listener {
++ /**
++ * a target accepts an offered mime type
++ *
++ * Sent when a target accepts pointer_focus or motion events. If
++ * a target does not accept any of the offered types, type is NULL.
++ *
++ * Used for feedback during drag-and-drop.
++ * @param mime_type mime type accepted by the target
++ */
++ void (*target)(void *data,
++ struct wl_data_source *wl_data_source,
++ const char *mime_type);
++ /**
++ * send the data
++ *
++ * Request for data from the client. Send the data as the
++ * specified mime type over the passed file descriptor, then close
++ * it.
++ * @param mime_type mime type for the data
++ * @param fd file descriptor for the data
++ */
++ void (*send)(void *data,
++ struct wl_data_source *wl_data_source,
++ const char *mime_type,
++ int32_t fd);
++ /**
++ * selection was cancelled
++ *
++ * This data source is no longer valid. There are several reasons
++ * why this could happen:
++ *
++ * - The data source has been replaced by another data source. -
++ * The drag-and-drop operation was performed, but the drop
++ * destination did not accept any of the mime types offered through
++ * wl_data_source.target. - The drag-and-drop operation was
++ * performed, but the drop destination did not select any of the
++ * actions present in the mask offered through
++ * wl_data_source.action. - The drag-and-drop operation was
++ * performed but didn't happen over a surface. - The compositor
++ * cancelled the drag-and-drop operation (e.g. compositor dependent
++ * timeouts to avoid stale drag-and-drop transfers).
++ *
++ * The client should clean up and destroy this data source.
++ *
++ * For objects of version 2 or older, wl_data_source.cancelled will
++ * only be emitted if the data source was replaced by another data
++ * source.
++ */
++ void (*cancelled)(void *data,
++ struct wl_data_source *wl_data_source);
++ /**
++ * the drag-and-drop operation physically finished
++ *
++ * The user performed the drop action. This event does not
++ * indicate acceptance, wl_data_source.cancelled may still be
++ * emitted afterwards if the drop destination does not accept any
++ * mime type.
++ *
++ * However, this event might however not be received if the
++ * compositor cancelled the drag-and-drop operation before this
++ * event could happen.
++ *
++ * Note that the data_source may still be used in the future and
++ * should not be destroyed here.
++ * @since 3
++ */
++ void (*dnd_drop_performed)(void *data,
++ struct wl_data_source *wl_data_source);
++ /**
++ * the drag-and-drop operation concluded
++ *
++ * The drop destination finished interoperating with this data
++ * source, so the client is now free to destroy this data source
++ * and free all associated data.
++ *
++ * If the action used to perform the operation was "move", the
++ * source can now delete the transferred data.
++ * @since 3
++ */
++ void (*dnd_finished)(void *data,
++ struct wl_data_source *wl_data_source);
++ /**
++ * notify the selected action
++ *
++ * This event indicates the action selected by the compositor
++ * after matching the source/destination side actions. Only one
++ * action (or none) will be offered here.
++ *
++ * This event can be emitted multiple times during the
++ * drag-and-drop operation, mainly in response to destination side
++ * changes through wl_data_offer.set_actions, and as the data
++ * device enters/leaves surfaces.
++ *
++ * It is only possible to receive this event after
++ * wl_data_source.dnd_drop_performed if the drag-and-drop operation
++ * ended in an "ask" action, in which case the final
++ * wl_data_source.action event will happen immediately before
++ * wl_data_source.dnd_finished.
++ *
++ * Compositors may also change the selected action on the fly,
++ * mainly in response to keyboard modifier changes during the
++ * drag-and-drop operation.
++ *
++ * The most recent action received is always the valid one. The
++ * chosen action may change alongside negotiation (e.g. an "ask"
++ * action can turn into a "move" operation), so the effects of the
++ * final action must always be applied in
++ * wl_data_offer.dnd_finished.
++ *
++ * Clients can trigger cursor surface changes from this point, so
++ * they reflect the current action.
++ * @param dnd_action action selected by the compositor
++ * @since 3
++ */
++ void (*action)(void *data,
++ struct wl_data_source *wl_data_source,
++ uint32_t dnd_action);
++};
++
++/**
++ * @ingroup iface_wl_data_source
++ */
++static inline int
++wl_data_source_add_listener(struct wl_data_source *wl_data_source,
++ const struct wl_data_source_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_data_source,
++ (void (**)(void)) listener, data);
++}
++
++#define WL_DATA_SOURCE_OFFER 0
++#define WL_DATA_SOURCE_DESTROY 1
++#define WL_DATA_SOURCE_SET_ACTIONS 2
++
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_TARGET_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_SEND_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_CANCELLED_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_ACTION_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_OFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION 3
++
++/** @ingroup iface_wl_data_source */
++static inline void
++wl_data_source_set_user_data(struct wl_data_source *wl_data_source, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_data_source, user_data);
++}
++
++/** @ingroup iface_wl_data_source */
++static inline void *
++wl_data_source_get_user_data(struct wl_data_source *wl_data_source)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_data_source);
++}
++
++static inline uint32_t
++wl_data_source_get_version(struct wl_data_source *wl_data_source)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_data_source);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ *
++ * This request adds a mime type to the set of mime types
++ * advertised to targets. Can be called several times to offer
++ * multiple types.
++ */
++static inline void
++wl_data_source_offer(struct wl_data_source *wl_data_source, const char *mime_type)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_data_source,
++ WL_DATA_SOURCE_OFFER, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_source), 0, mime_type);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ *
++ * Destroy the data source.
++ */
++static inline void
++wl_data_source_destroy(struct wl_data_source *wl_data_source)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_data_source,
++ WL_DATA_SOURCE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_source), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ *
++ * Sets the actions that the source side client supports for this
++ * operation. This request may trigger wl_data_source.action and
++ * wl_data_offer.action events if the compositor needs to change the
++ * selected action.
++ *
++ * The dnd_actions argument must contain only values expressed in the
++ * wl_data_device_manager.dnd_actions enum, otherwise it will result
++ * in a protocol error.
++ *
++ * This request must be made once only, and can only be made on sources
++ * used in drag-and-drop, so it must be performed before
++ * wl_data_device.start_drag. Attempting to use the source other than
++ * for drag-and-drop will raise a protocol error.
++ */
++static inline void
++wl_data_source_set_actions(struct wl_data_source *wl_data_source, uint32_t dnd_actions)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_data_source,
++ WL_DATA_SOURCE_SET_ACTIONS, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_source), 0, dnd_actions);
++}
++
++#ifndef WL_DATA_DEVICE_ERROR_ENUM
++#define WL_DATA_DEVICE_ERROR_ENUM
++enum wl_data_device_error {
++ /**
++ * given wl_surface has another role
++ */
++ WL_DATA_DEVICE_ERROR_ROLE = 0,
++};
++#endif /* WL_DATA_DEVICE_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_data_device
++ * @struct wl_data_device_listener
++ */
++struct wl_data_device_listener {
++ /**
++ * introduce a new wl_data_offer
++ *
++ * The data_offer event introduces a new wl_data_offer object,
++ * which will subsequently be used in either the data_device.enter
++ * event (for drag-and-drop) or the data_device.selection event
++ * (for selections). Immediately following the
++ * data_device.data_offer event, the new data_offer object will
++ * send out data_offer.offer events to describe the mime types it
++ * offers.
++ * @param id the new data_offer object
++ */
++ void (*data_offer)(void *data,
++ struct wl_data_device *wl_data_device,
++ struct wl_data_offer *id);
++ /**
++ * initiate drag-and-drop session
++ *
++ * This event is sent when an active drag-and-drop pointer enters
++ * a surface owned by the client. The position of the pointer at
++ * enter time is provided by the x and y arguments, in
++ * surface-local coordinates.
++ * @param serial serial number of the enter event
++ * @param surface client surface entered
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ * @param id source data_offer object
++ */
++ void (*enter)(void *data,
++ struct wl_data_device *wl_data_device,
++ uint32_t serial,
++ struct wl_surface *surface,
++ wl_fixed_t x,
++ wl_fixed_t y,
++ struct wl_data_offer *id);
++ /**
++ * end drag-and-drop session
++ *
++ * This event is sent when the drag-and-drop pointer leaves the
++ * surface and the session ends. The client must destroy the
++ * wl_data_offer introduced at enter time at this point.
++ */
++ void (*leave)(void *data,
++ struct wl_data_device *wl_data_device);
++ /**
++ * drag-and-drop session motion
++ *
++ * This event is sent when the drag-and-drop pointer moves within
++ * the currently focused surface. The new position of the pointer
++ * is provided by the x and y arguments, in surface-local
++ * coordinates.
++ * @param time timestamp with millisecond granularity
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ */
++ void (*motion)(void *data,
++ struct wl_data_device *wl_data_device,
++ uint32_t time,
++ wl_fixed_t x,
++ wl_fixed_t y);
++ /**
++ * end drag-and-drop session successfully
++ *
++ * The event is sent when a drag-and-drop operation is ended
++ * because the implicit grab is removed.
++ *
++ * The drag-and-drop destination is expected to honor the last
++ * action received through wl_data_offer.action, if the resulting
++ * action is "copy" or "move", the destination can still perform
++ * wl_data_offer.receive requests, and is expected to end all
++ * transfers with a wl_data_offer.finish request.
++ *
++ * If the resulting action is "ask", the action will not be
++ * considered final. The drag-and-drop destination is expected to
++ * perform one last wl_data_offer.set_actions request, or
++ * wl_data_offer.destroy in order to cancel the operation.
++ */
++ void (*drop)(void *data,
++ struct wl_data_device *wl_data_device);
++ /**
++ * advertise new selection
++ *
++ * The selection event is sent out to notify the client of a new
++ * wl_data_offer for the selection for this device. The
++ * data_device.data_offer and the data_offer.offer events are sent
++ * out immediately before this event to introduce the data offer
++ * object. The selection event is sent to a client immediately
++ * before receiving keyboard focus and when a new selection is set
++ * while the client has keyboard focus. The data_offer is valid
++ * until a new data_offer or NULL is received or until the client
++ * loses keyboard focus. The client must destroy the previous
++ * selection data_offer, if any, upon receiving this event.
++ * @param id selection data_offer object
++ */
++ void (*selection)(void *data,
++ struct wl_data_device *wl_data_device,
++ struct wl_data_offer *id);
++};
++
++/**
++ * @ingroup iface_wl_data_device
++ */
++static inline int
++wl_data_device_add_listener(struct wl_data_device *wl_data_device,
++ const struct wl_data_device_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_data_device,
++ (void (**)(void)) listener, data);
++}
++
++#define WL_DATA_DEVICE_START_DRAG 0
++#define WL_DATA_DEVICE_SET_SELECTION 1
++#define WL_DATA_DEVICE_RELEASE 2
++
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_DATA_OFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_LEAVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_MOTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_DROP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_SELECTION_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_START_DRAG_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_SET_SELECTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_RELEASE_SINCE_VERSION 2
++
++/** @ingroup iface_wl_data_device */
++static inline void
++wl_data_device_set_user_data(struct wl_data_device *wl_data_device, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_data_device, user_data);
++}
++
++/** @ingroup iface_wl_data_device */
++static inline void *
++wl_data_device_get_user_data(struct wl_data_device *wl_data_device)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_data_device);
++}
++
++static inline uint32_t
++wl_data_device_get_version(struct wl_data_device *wl_data_device)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_data_device);
++}
++
++/** @ingroup iface_wl_data_device */
++static inline void
++wl_data_device_destroy(struct wl_data_device *wl_data_device)
++{
++ wl_proxy_destroy((struct wl_proxy *) wl_data_device);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ *
++ * This request asks the compositor to start a drag-and-drop
++ * operation on behalf of the client.
++ *
++ * The source argument is the data source that provides the data
++ * for the eventual data transfer. If source is NULL, enter, leave
++ * and motion events are sent only to the client that initiated the
++ * drag and the client is expected to handle the data passing
++ * internally.
++ *
++ * The origin surface is the surface where the drag originates and
++ * the client must have an active implicit grab that matches the
++ * serial.
++ *
++ * The icon surface is an optional (can be NULL) surface that
++ * provides an icon to be moved around with the cursor. Initially,
++ * the top-left corner of the icon surface is placed at the cursor
++ * hotspot, but subsequent wl_surface.attach request can move the
++ * relative position. Attach requests must be confirmed with
++ * wl_surface.commit as usual. The icon surface is given the role of
++ * a drag-and-drop icon. If the icon surface already has another role,
++ * it raises a protocol error.
++ *
++ * The current and pending input regions of the icon wl_surface are
++ * cleared, and wl_surface.set_input_region is ignored until the
++ * wl_surface is no longer used as the icon surface. When the use
++ * as an icon ends, the current and pending input regions become
++ * undefined, and the wl_surface is unmapped.
++ */
++static inline void
++wl_data_device_start_drag(struct wl_data_device *wl_data_device, struct wl_data_source *source, struct wl_surface *origin, struct wl_surface *icon, uint32_t serial)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device,
++ WL_DATA_DEVICE_START_DRAG, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_device), 0, source, origin, icon, serial);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ *
++ * This request asks the compositor to set the selection
++ * to the data from the source on behalf of the client.
++ *
++ * To unset the selection, set the source to NULL.
++ */
++static inline void
++wl_data_device_set_selection(struct wl_data_device *wl_data_device, struct wl_data_source *source, uint32_t serial)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device,
++ WL_DATA_DEVICE_SET_SELECTION, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_device), 0, source, serial);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ *
++ * This request destroys the data device.
++ */
++static inline void
++wl_data_device_release(struct wl_data_device *wl_data_device)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device,
++ WL_DATA_DEVICE_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_device), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#ifndef WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM
++#define WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM
++/**
++ * @ingroup iface_wl_data_device_manager
++ * drag and drop actions
++ *
++ * This is a bitmask of the available/preferred actions in a
++ * drag-and-drop operation.
++ *
++ * In the compositor, the selected action is a result of matching the
++ * actions offered by the source and destination sides. "action" events
++ * with a "none" action will be sent to both source and destination if
++ * there is no match. All further checks will effectively happen on
++ * (source actions ∩ destination actions).
++ *
++ * In addition, compositors may also pick different actions in
++ * reaction to key modifiers being pressed. One common design that
++ * is used in major toolkits (and the behavior recommended for
++ * compositors) is:
++ *
++ * - If no modifiers are pressed, the first match (in bit order)
++ * will be used.
++ * - Pressing Shift selects "move", if enabled in the mask.
++ * - Pressing Control selects "copy", if enabled in the mask.
++ *
++ * Behavior beyond that is considered implementation-dependent.
++ * Compositors may for example bind other modifiers (like Alt/Meta)
++ * or drags initiated with other buttons than BTN_LEFT to specific
++ * actions (e.g. "ask").
++ */
++enum wl_data_device_manager_dnd_action {
++ /**
++ * no action
++ */
++ WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE = 0,
++ /**
++ * copy action
++ */
++ WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY = 1,
++ /**
++ * move action
++ */
++ WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE = 2,
++ /**
++ * ask action
++ */
++ WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK = 4,
++};
++#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM */
++
++#define WL_DATA_DEVICE_MANAGER_CREATE_DATA_SOURCE 0
++#define WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE 1
++
++
++/**
++ * @ingroup iface_wl_data_device_manager
++ */
++#define WL_DATA_DEVICE_MANAGER_CREATE_DATA_SOURCE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device_manager
++ */
++#define WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE_SINCE_VERSION 1
++
++/** @ingroup iface_wl_data_device_manager */
++static inline void
++wl_data_device_manager_set_user_data(struct wl_data_device_manager *wl_data_device_manager, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_data_device_manager, user_data);
++}
++
++/** @ingroup iface_wl_data_device_manager */
++static inline void *
++wl_data_device_manager_get_user_data(struct wl_data_device_manager *wl_data_device_manager)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_data_device_manager);
++}
++
++static inline uint32_t
++wl_data_device_manager_get_version(struct wl_data_device_manager *wl_data_device_manager)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_data_device_manager);
++}
++
++/** @ingroup iface_wl_data_device_manager */
++static inline void
++wl_data_device_manager_destroy(struct wl_data_device_manager *wl_data_device_manager)
++{
++ wl_proxy_destroy((struct wl_proxy *) wl_data_device_manager);
++}
++
++/**
++ * @ingroup iface_wl_data_device_manager
++ *
++ * Create a new data source.
++ */
++static inline struct wl_data_source *
++wl_data_device_manager_create_data_source(struct wl_data_device_manager *wl_data_device_manager)
++{
++ struct wl_proxy *id;
++
++ id = wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device_manager,
++ WL_DATA_DEVICE_MANAGER_CREATE_DATA_SOURCE, &wl_data_source_interface, wl_proxy_get_version((struct wl_proxy *) wl_data_device_manager), 0, NULL);
++
++ return (struct wl_data_source *) id;
++}
++
++/**
++ * @ingroup iface_wl_data_device_manager
++ *
++ * Create a new data device for a given seat.
++ */
++static inline struct wl_data_device *
++wl_data_device_manager_get_data_device(struct wl_data_device_manager *wl_data_device_manager, struct wl_seat *seat)
++{
++ struct wl_proxy *id;
++
++ id = wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device_manager,
++ WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE, &wl_data_device_interface, wl_proxy_get_version((struct wl_proxy *) wl_data_device_manager), 0, NULL, seat);
++
++ return (struct wl_data_device *) id;
++}
++
++#ifndef WL_SHELL_ERROR_ENUM
++#define WL_SHELL_ERROR_ENUM
++enum wl_shell_error {
++ /**
++ * given wl_surface has another role
++ */
++ WL_SHELL_ERROR_ROLE = 0,
++};
++#endif /* WL_SHELL_ERROR_ENUM */
++
++#define WL_SHELL_GET_SHELL_SURFACE 0
++
++
++/**
++ * @ingroup iface_wl_shell
++ */
++#define WL_SHELL_GET_SHELL_SURFACE_SINCE_VERSION 1
++
++/** @ingroup iface_wl_shell */
++static inline void
++wl_shell_set_user_data(struct wl_shell *wl_shell, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_shell, user_data);
++}
++
++/** @ingroup iface_wl_shell */
++static inline void *
++wl_shell_get_user_data(struct wl_shell *wl_shell)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_shell);
++}
++
++static inline uint32_t
++wl_shell_get_version(struct wl_shell *wl_shell)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_shell);
++}
++
++/** @ingroup iface_wl_shell */
++static inline void
++wl_shell_destroy(struct wl_shell *wl_shell)
++{
++ wl_proxy_destroy((struct wl_proxy *) wl_shell);
++}
++
++/**
++ * @ingroup iface_wl_shell
++ *
++ * Create a shell surface for an existing surface. This gives
++ * the wl_surface the role of a shell surface. If the wl_surface
++ * already has another role, it raises a protocol error.
++ *
++ * Only one shell surface can be associated with a given surface.
++ */
++static inline struct wl_shell_surface *
++wl_shell_get_shell_surface(struct wl_shell *wl_shell, struct wl_surface *surface)
++{
++ struct wl_proxy *id;
++
++ id = wl_proxy_marshal_flags((struct wl_proxy *) wl_shell,
++ WL_SHELL_GET_SHELL_SURFACE, &wl_shell_surface_interface, wl_proxy_get_version((struct wl_proxy *) wl_shell), 0, NULL, surface);
++
++ return (struct wl_shell_surface *) id;
++}
++
++#ifndef WL_SHELL_SURFACE_RESIZE_ENUM
++#define WL_SHELL_SURFACE_RESIZE_ENUM
++/**
++ * @ingroup iface_wl_shell_surface
++ * edge values for resizing
++ *
++ * These values are used to indicate which edge of a surface
++ * is being dragged in a resize operation. The server may
++ * use this information to adapt its behavior, e.g. choose
++ * an appropriate cursor image.
++ */
++enum wl_shell_surface_resize {
++ /**
++ * no edge
++ */
++ WL_SHELL_SURFACE_RESIZE_NONE = 0,
++ /**
++ * top edge
++ */
++ WL_SHELL_SURFACE_RESIZE_TOP = 1,
++ /**
++ * bottom edge
++ */
++ WL_SHELL_SURFACE_RESIZE_BOTTOM = 2,
++ /**
++ * left edge
++ */
++ WL_SHELL_SURFACE_RESIZE_LEFT = 4,
++ /**
++ * top and left edges
++ */
++ WL_SHELL_SURFACE_RESIZE_TOP_LEFT = 5,
++ /**
++ * bottom and left edges
++ */
++ WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT = 6,
++ /**
++ * right edge
++ */
++ WL_SHELL_SURFACE_RESIZE_RIGHT = 8,
++ /**
++ * top and right edges
++ */
++ WL_SHELL_SURFACE_RESIZE_TOP_RIGHT = 9,
++ /**
++ * bottom and right edges
++ */
++ WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT = 10,
++};
++#endif /* WL_SHELL_SURFACE_RESIZE_ENUM */
++
++#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM
++#define WL_SHELL_SURFACE_TRANSIENT_ENUM
++/**
++ * @ingroup iface_wl_shell_surface
++ * details of transient behaviour
++ *
++ * These flags specify details of the expected behaviour
++ * of transient surfaces. Used in the set_transient request.
++ */
++enum wl_shell_surface_transient {
++ /**
++ * do not set keyboard focus
++ */
++ WL_SHELL_SURFACE_TRANSIENT_INACTIVE = 0x1,
++};
++#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM */
++
++#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
++#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
++/**
++ * @ingroup iface_wl_shell_surface
++ * different method to set the surface fullscreen
++ *
++ * Hints to indicate to the compositor how to deal with a conflict
++ * between the dimensions of the surface and the dimensions of the
++ * output. The compositor is free to ignore this parameter.
++ */
++enum wl_shell_surface_fullscreen_method {
++ /**
++ * no preference, apply default policy
++ */
++ WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT = 0,
++ /**
++ * scale, preserve the surface's aspect ratio and center on output
++ */
++ WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE = 1,
++ /**
++ * switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch
++ */
++ WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER = 2,
++ /**
++ * no upscaling, center on output and add black borders to compensate size mismatch
++ */
++ WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL = 3,
++};
++#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM */
++
++/**
++ * @ingroup iface_wl_shell_surface
++ * @struct wl_shell_surface_listener
++ */
++struct wl_shell_surface_listener {
++ /**
++ * ping client
++ *
++ * Ping a client to check if it is receiving events and sending
++ * requests. A client is expected to reply with a pong request.
++ * @param serial serial number of the ping
++ */
++ void (*ping)(void *data,
++ struct wl_shell_surface *wl_shell_surface,
++ uint32_t serial);
++ /**
++ * suggest resize
++ *
++ * The configure event asks the client to resize its surface.
++ *
++ * The size is a hint, in the sense that the client is free to
++ * ignore it if it doesn't resize, pick a smaller size (to satisfy
++ * aspect ratio or resize in steps of NxM pixels).
++ *
++ * The edges parameter provides a hint about how the surface was
++ * resized. The client may use this information to decide how to
++ * adjust its content to the new size (e.g. a scrolling area might
++ * adjust its content position to leave the viewable content
++ * unmoved).
++ *
++ * The client is free to dismiss all but the last configure event
++ * it received.
++ *
++ * The width and height arguments specify the size of the window in
++ * surface-local coordinates.
++ * @param edges how the surface was resized
++ * @param width new width of the surface
++ * @param height new height of the surface
++ */
++ void (*configure)(void *data,
++ struct wl_shell_surface *wl_shell_surface,
++ uint32_t edges,
++ int32_t width,
++ int32_t height);
++ /**
++ * popup interaction is done
++ *
++ * The popup_done event is sent out when a popup grab is broken,
++ * that is, when the user clicks a surface that doesn't belong to
++ * the client owning the popup surface.
++ */
++ void (*popup_done)(void *data,
++ struct wl_shell_surface *wl_shell_surface);
++};
++
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++static inline int
++wl_shell_surface_add_listener(struct wl_shell_surface *wl_shell_surface,
++ const struct wl_shell_surface_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_shell_surface,
++ (void (**)(void)) listener, data);
++}
++
++#define WL_SHELL_SURFACE_PONG 0
++#define WL_SHELL_SURFACE_MOVE 1
++#define WL_SHELL_SURFACE_RESIZE 2
++#define WL_SHELL_SURFACE_SET_TOPLEVEL 3
++#define WL_SHELL_SURFACE_SET_TRANSIENT 4
++#define WL_SHELL_SURFACE_SET_FULLSCREEN 5
++#define WL_SHELL_SURFACE_SET_POPUP 6
++#define WL_SHELL_SURFACE_SET_MAXIMIZED 7
++#define WL_SHELL_SURFACE_SET_TITLE 8
++#define WL_SHELL_SURFACE_SET_CLASS 9
++
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_PING_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_CONFIGURE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_POPUP_DONE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_PONG_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_MOVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_RESIZE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_TOPLEVEL_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_TRANSIENT_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_FULLSCREEN_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_POPUP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_MAXIMIZED_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_TITLE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_CLASS_SINCE_VERSION 1
++
++/** @ingroup iface_wl_shell_surface */
++static inline void
++wl_shell_surface_set_user_data(struct wl_shell_surface *wl_shell_surface, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_shell_surface, user_data);
++}
++
++/** @ingroup iface_wl_shell_surface */
++static inline void *
++wl_shell_surface_get_user_data(struct wl_shell_surface *wl_shell_surface)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_shell_surface);
++}
++
++static inline uint32_t
++wl_shell_surface_get_version(struct wl_shell_surface *wl_shell_surface)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_shell_surface);
++}
++
++/** @ingroup iface_wl_shell_surface */
++static inline void
++wl_shell_surface_destroy(struct wl_shell_surface *wl_shell_surface)
++{
++ wl_proxy_destroy((struct wl_proxy *) wl_shell_surface);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * A client must respond to a ping event with a pong request or
++ * the client may be deemed unresponsive.
++ */
++static inline void
++wl_shell_surface_pong(struct wl_shell_surface *wl_shell_surface, uint32_t serial)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++ WL_SHELL_SURFACE_PONG, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, serial);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Start a pointer-driven move of the surface.
++ *
++ * This request must be used in response to a button press event.
++ * The server may ignore move requests depending on the state of
++ * the surface (e.g. fullscreen or maximized).
++ */
++static inline void
++wl_shell_surface_move(struct wl_shell_surface *wl_shell_surface, struct wl_seat *seat, uint32_t serial)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++ WL_SHELL_SURFACE_MOVE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, seat, serial);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Start a pointer-driven resizing of the surface.
++ *
++ * This request must be used in response to a button press event.
++ * The server may ignore resize requests depending on the state of
++ * the surface (e.g. fullscreen or maximized).
++ */
++static inline void
++wl_shell_surface_resize(struct wl_shell_surface *wl_shell_surface, struct wl_seat *seat, uint32_t serial, uint32_t edges)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++ WL_SHELL_SURFACE_RESIZE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, seat, serial, edges);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Map the surface as a toplevel surface.
++ *
++ * A toplevel surface is not fullscreen, maximized or transient.
++ */
++static inline void
++wl_shell_surface_set_toplevel(struct wl_shell_surface *wl_shell_surface)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++ WL_SHELL_SURFACE_SET_TOPLEVEL, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Map the surface relative to an existing surface.
++ *
++ * The x and y arguments specify the location of the upper left
++ * corner of the surface relative to the upper left corner of the
++ * parent surface, in surface-local coordinates.
++ *
++ * The flags argument controls details of the transient behaviour.
++ */
++static inline void
++wl_shell_surface_set_transient(struct wl_shell_surface *wl_shell_surface, struct wl_surface *parent, int32_t x, int32_t y, uint32_t flags)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++ WL_SHELL_SURFACE_SET_TRANSIENT, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, parent, x, y, flags);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Map the surface as a fullscreen surface.
++ *
++ * If an output parameter is given then the surface will be made
++ * fullscreen on that output. If the client does not specify the
++ * output then the compositor will apply its policy - usually
++ * choosing the output on which the surface has the biggest surface
++ * area.
++ *
++ * The client may specify a method to resolve a size conflict
++ * between the output size and the surface size - this is provided
++ * through the method parameter.
++ *
++ * The framerate parameter is used only when the method is set
++ * to "driver", to indicate the preferred framerate. A value of 0
++ * indicates that the client does not care about framerate. The
++ * framerate is specified in mHz, that is framerate of 60000 is 60Hz.
++ *
++ * A method of "scale" or "driver" implies a scaling operation of
++ * the surface, either via a direct scaling operation or a change of
++ * the output mode. This will override any kind of output scaling, so
++ * that mapping a surface with a buffer size equal to the mode can
++ * fill the screen independent of buffer_scale.
++ *
++ * A method of "fill" means we don't scale up the buffer, however
++ * any output scale is applied. This means that you may run into
++ * an edge case where the application maps a buffer with the same
++ * size of the output mode but buffer_scale 1 (thus making a
++ * surface larger than the output). In this case it is allowed to
++ * downscale the results to fit the screen.
++ *
++ * The compositor must reply to this request with a configure event
++ * with the dimensions for the output on which the surface will
++ * be made fullscreen.
++ */
++static inline void
++wl_shell_surface_set_fullscreen(struct wl_shell_surface *wl_shell_surface, uint32_t method, uint32_t framerate, struct wl_output *output)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++ WL_SHELL_SURFACE_SET_FULLSCREEN, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, method, framerate, output);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Map the surface as a popup.
++ *
++ * A popup surface is a transient surface with an added pointer
++ * grab.
++ *
++ * An existing implicit grab will be changed to owner-events mode,
++ * and the popup grab will continue after the implicit grab ends
++ * (i.e. releasing the mouse button does not cause the popup to
++ * be unmapped).
++ *
++ * The popup grab continues until the window is destroyed or a
++ * mouse button is pressed in any other client's window. A click
++ * in any of the client's surfaces is reported as normal, however,
++ * clicks in other clients' surfaces will be discarded and trigger
++ * the callback.
++ *
++ * The x and y arguments specify the location of the upper left
++ * corner of the surface relative to the upper left corner of the
++ * parent surface, in surface-local coordinates.
++ */
++static inline void
++wl_shell_surface_set_popup(struct wl_shell_surface *wl_shell_surface, struct wl_seat *seat, uint32_t serial, struct wl_surface *parent, int32_t x, int32_t y, uint32_t flags)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++ WL_SHELL_SURFACE_SET_POPUP, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, seat, serial, parent, x, y, flags);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Map the surface as a maximized surface.
++ *
++ * If an output parameter is given then the surface will be
++ * maximized on that output. If the client does not specify the
++ * output then the compositor will apply its policy - usually
++ * choosing the output on which the surface has the biggest surface
++ * area.
++ *
++ * The compositor will reply with a configure event telling
++ * the expected new surface size. The operation is completed
++ * on the next buffer attach to this surface.
++ *
++ * A maximized surface typically fills the entire output it is
++ * bound to, except for desktop elements such as panels. This is
++ * the main difference between a maximized shell surface and a
++ * fullscreen shell surface.
++ *
++ * The details depend on the compositor implementation.
++ */
++static inline void
++wl_shell_surface_set_maximized(struct wl_shell_surface *wl_shell_surface, struct wl_output *output)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++ WL_SHELL_SURFACE_SET_MAXIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, output);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Set a short title for the surface.
++ *
++ * This string may be used to identify the surface in a task bar,
++ * window list, or other user interface elements provided by the
++ * compositor.
++ *
++ * The string must be encoded in UTF-8.
++ */
++static inline void
++wl_shell_surface_set_title(struct wl_shell_surface *wl_shell_surface, const char *title)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++ WL_SHELL_SURFACE_SET_TITLE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, title);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Set a class for the surface.
++ *
++ * The surface class identifies the general class of applications
++ * to which the surface belongs. A common convention is to use the
++ * file name (or the full path if it is a non-standard location) of
++ * the application's .desktop file as the class.
++ */
++static inline void
++wl_shell_surface_set_class(struct wl_shell_surface *wl_shell_surface, const char *class_)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++ WL_SHELL_SURFACE_SET_CLASS, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, class_);
++}
++
++#ifndef WL_SURFACE_ERROR_ENUM
++#define WL_SURFACE_ERROR_ENUM
++/**
++ * @ingroup iface_wl_surface
++ * wl_surface error values
++ *
++ * These errors can be emitted in response to wl_surface requests.
++ */
++enum wl_surface_error {
++ /**
++ * buffer scale value is invalid
++ */
++ WL_SURFACE_ERROR_INVALID_SCALE = 0,
++ /**
++ * buffer transform value is invalid
++ */
++ WL_SURFACE_ERROR_INVALID_TRANSFORM = 1,
++};
++#endif /* WL_SURFACE_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_surface
++ * @struct wl_surface_listener
++ */
++struct wl_surface_listener {
++ /**
++ * surface enters an output
++ *
++ * This is emitted whenever a surface's creation, movement, or
++ * resizing results in some part of it being within the scanout
++ * region of an output.
++ *
++ * Note that a surface may be overlapping with zero or more
++ * outputs.
++ * @param output output entered by the surface
++ */
++ void (*enter)(void *data,
++ struct wl_surface *wl_surface,
++ struct wl_output *output);
++ /**
++ * surface leaves an output
++ *
++ * This is emitted whenever a surface's creation, movement, or
++ * resizing results in it no longer having any part of it within
++ * the scanout region of an output.
++ * @param output output left by the surface
++ */
++ void (*leave)(void *data,
++ struct wl_surface *wl_surface,
++ struct wl_output *output);
++};
++
++/**
++ * @ingroup iface_wl_surface
++ */
++static inline int
++wl_surface_add_listener(struct wl_surface *wl_surface,
++ const struct wl_surface_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_surface,
++ (void (**)(void)) listener, data);
++}
++
++#define WL_SURFACE_DESTROY 0
++#define WL_SURFACE_ATTACH 1
++#define WL_SURFACE_DAMAGE 2
++#define WL_SURFACE_FRAME 3
++#define WL_SURFACE_SET_OPAQUE_REGION 4
++#define WL_SURFACE_SET_INPUT_REGION 5
++#define WL_SURFACE_COMMIT 6
++#define WL_SURFACE_SET_BUFFER_TRANSFORM 7
++#define WL_SURFACE_SET_BUFFER_SCALE 8
++#define WL_SURFACE_DAMAGE_BUFFER 9
++
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_LEAVE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_ATTACH_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_DAMAGE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_FRAME_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_OPAQUE_REGION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_INPUT_REGION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_COMMIT_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_BUFFER_TRANSFORM_SINCE_VERSION 2
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION 4
++
++/** @ingroup iface_wl_surface */
++static inline void
++wl_surface_set_user_data(struct wl_surface *wl_surface, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_surface, user_data);
++}
++
++/** @ingroup iface_wl_surface */
++static inline void *
++wl_surface_get_user_data(struct wl_surface *wl_surface)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_surface);
++}
++
++static inline uint32_t
++wl_surface_get_version(struct wl_surface *wl_surface)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_surface);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * Deletes the surface and invalidates its object ID.
++ */
++static inline void
++wl_surface_destroy(struct wl_surface *wl_surface)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++ WL_SURFACE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * Set a buffer as the content of this surface.
++ *
++ * The new size of the surface is calculated based on the buffer
++ * size transformed by the inverse buffer_transform and the
++ * inverse buffer_scale. This means that the supplied buffer
++ * must be an integer multiple of the buffer_scale.
++ *
++ * The x and y arguments specify the location of the new pending
++ * buffer's upper left corner, relative to the current buffer's upper
++ * left corner, in surface-local coordinates. In other words, the
++ * x and y, combined with the new surface size define in which
++ * directions the surface's size changes.
++ *
++ * Surface contents are double-buffered state, see wl_surface.commit.
++ *
++ * The initial surface contents are void; there is no content.
++ * wl_surface.attach assigns the given wl_buffer as the pending
++ * wl_buffer. wl_surface.commit makes the pending wl_buffer the new
++ * surface contents, and the size of the surface becomes the size
++ * calculated from the wl_buffer, as described above. After commit,
++ * there is no pending buffer until the next attach.
++ *
++ * Committing a pending wl_buffer allows the compositor to read the
++ * pixels in the wl_buffer. The compositor may access the pixels at
++ * any time after the wl_surface.commit request. When the compositor
++ * will not access the pixels anymore, it will send the
++ * wl_buffer.release event. Only after receiving wl_buffer.release,
++ * the client may reuse the wl_buffer. A wl_buffer that has been
++ * attached and then replaced by another attach instead of committed
++ * will not receive a release event, and is not used by the
++ * compositor.
++ *
++ * Destroying the wl_buffer after wl_buffer.release does not change
++ * the surface contents. However, if the client destroys the
++ * wl_buffer before receiving the wl_buffer.release event, the surface
++ * contents become undefined immediately.
++ *
++ * If wl_surface.attach is sent with a NULL wl_buffer, the
++ * following wl_surface.commit will remove the surface content.
++ */
++static inline void
++wl_surface_attach(struct wl_surface *wl_surface, struct wl_buffer *buffer, int32_t x, int32_t y)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++ WL_SURFACE_ATTACH, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, buffer, x, y);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * This request is used to describe the regions where the pending
++ * buffer is different from the current surface contents, and where
++ * the surface therefore needs to be repainted. The compositor
++ * ignores the parts of the damage that fall outside of the surface.
++ *
++ * Damage is double-buffered state, see wl_surface.commit.
++ *
++ * The damage rectangle is specified in surface-local coordinates,
++ * where x and y specify the upper left corner of the damage rectangle.
++ *
++ * The initial value for pending damage is empty: no damage.
++ * wl_surface.damage adds pending damage: the new pending damage
++ * is the union of old pending damage and the given rectangle.
++ *
++ * wl_surface.commit assigns pending damage as the current damage,
++ * and clears pending damage. The server will clear the current
++ * damage as it repaints the surface.
++ *
++ * Alternatively, damage can be posted with wl_surface.damage_buffer
++ * which uses buffer coordinates instead of surface coordinates,
++ * and is probably the preferred and intuitive way of doing this.
++ */
++static inline void
++wl_surface_damage(struct wl_surface *wl_surface, int32_t x, int32_t y, int32_t width, int32_t height)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++ WL_SURFACE_DAMAGE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, x, y, width, height);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * Request a notification when it is a good time to start drawing a new
++ * frame, by creating a frame callback. This is useful for throttling
++ * redrawing operations, and driving animations.
++ *
++ * When a client is animating on a wl_surface, it can use the 'frame'
++ * request to get notified when it is a good time to draw and commit the
++ * next frame of animation. If the client commits an update earlier than
++ * that, it is likely that some updates will not make it to the display,
++ * and the client is wasting resources by drawing too often.
++ *
++ * The frame request will take effect on the next wl_surface.commit.
++ * The notification will only be posted for one frame unless
++ * requested again. For a wl_surface, the notifications are posted in
++ * the order the frame requests were committed.
++ *
++ * The server must send the notifications so that a client
++ * will not send excessive updates, while still allowing
++ * the highest possible update rate for clients that wait for the reply
++ * before drawing again. The server should give some time for the client
++ * to draw and commit after sending the frame callback events to let it
++ * hit the next output refresh.
++ *
++ * A server should avoid signaling the frame callbacks if the
++ * surface is not visible in any way, e.g. the surface is off-screen,
++ * or completely obscured by other opaque surfaces.
++ *
++ * The object returned by this request will be destroyed by the
++ * compositor after the callback is fired and as such the client must not
++ * attempt to use it after that point.
++ *
++ * The callback_data passed in the callback is the current time, in
++ * milliseconds, with an undefined base.
++ */
++static inline struct wl_callback *
++wl_surface_frame(struct wl_surface *wl_surface)
++{
++ struct wl_proxy *callback;
++
++ callback = wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++ WL_SURFACE_FRAME, &wl_callback_interface, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, NULL);
++
++ return (struct wl_callback *) callback;
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * This request sets the region of the surface that contains
++ * opaque content.
++ *
++ * The opaque region is an optimization hint for the compositor
++ * that lets it optimize the redrawing of content behind opaque
++ * regions. Setting an opaque region is not required for correct
++ * behaviour, but marking transparent content as opaque will result
++ * in repaint artifacts.
++ *
++ * The opaque region is specified in surface-local coordinates.
++ *
++ * The compositor ignores the parts of the opaque region that fall
++ * outside of the surface.
++ *
++ * Opaque region is double-buffered state, see wl_surface.commit.
++ *
++ * wl_surface.set_opaque_region changes the pending opaque region.
++ * wl_surface.commit copies the pending region to the current region.
++ * Otherwise, the pending and current regions are never changed.
++ *
++ * The initial value for an opaque region is empty. Setting the pending
++ * opaque region has copy semantics, and the wl_region object can be
++ * destroyed immediately. A NULL wl_region causes the pending opaque
++ * region to be set to empty.
++ */
++static inline void
++wl_surface_set_opaque_region(struct wl_surface *wl_surface, struct wl_region *region)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++ WL_SURFACE_SET_OPAQUE_REGION, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, region);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * This request sets the region of the surface that can receive
++ * pointer and touch events.
++ *
++ * Input events happening outside of this region will try the next
++ * surface in the server surface stack. The compositor ignores the
++ * parts of the input region that fall outside of the surface.
++ *
++ * The input region is specified in surface-local coordinates.
++ *
++ * Input region is double-buffered state, see wl_surface.commit.
++ *
++ * wl_surface.set_input_region changes the pending input region.
++ * wl_surface.commit copies the pending region to the current region.
++ * Otherwise the pending and current regions are never changed,
++ * except cursor and icon surfaces are special cases, see
++ * wl_pointer.set_cursor and wl_data_device.start_drag.
++ *
++ * The initial value for an input region is infinite. That means the
++ * whole surface will accept input. Setting the pending input region
++ * has copy semantics, and the wl_region object can be destroyed
++ * immediately. A NULL wl_region causes the input region to be set
++ * to infinite.
++ */
++static inline void
++wl_surface_set_input_region(struct wl_surface *wl_surface, struct wl_region *region)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++ WL_SURFACE_SET_INPUT_REGION, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, region);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * Surface state (input, opaque, and damage regions, attached buffers,
++ * etc.) is double-buffered. Protocol requests modify the pending state,
++ * as opposed to the current state in use by the compositor. A commit
++ * request atomically applies all pending state, replacing the current
++ * state. After commit, the new pending state is as documented for each
++ * related request.
++ *
++ * On commit, a pending wl_buffer is applied first, and all other state
++ * second. This means that all coordinates in double-buffered state are
++ * relative to the new wl_buffer coming into use, except for
++ * wl_surface.attach itself. If there is no pending wl_buffer, the
++ * coordinates are relative to the current surface contents.
++ *
++ * All requests that need a commit to become effective are documented
++ * to affect double-buffered state.
++ *
++ * Other interfaces may add further double-buffered surface state.
++ */
++static inline void
++wl_surface_commit(struct wl_surface *wl_surface)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++ WL_SURFACE_COMMIT, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * This request sets an optional transformation on how the compositor
++ * interprets the contents of the buffer attached to the surface. The
++ * accepted values for the transform parameter are the values for
++ * wl_output.transform.
++ *
++ * Buffer transform is double-buffered state, see wl_surface.commit.
++ *
++ * A newly created surface has its buffer transformation set to normal.
++ *
++ * wl_surface.set_buffer_transform changes the pending buffer
++ * transformation. wl_surface.commit copies the pending buffer
++ * transformation to the current one. Otherwise, the pending and current
++ * values are never changed.
++ *
++ * The purpose of this request is to allow clients to render content
++ * according to the output transform, thus permitting the compositor to
++ * use certain optimizations even if the display is rotated. Using
++ * hardware overlays and scanning out a client buffer for fullscreen
++ * surfaces are examples of such optimizations. Those optimizations are
++ * highly dependent on the compositor implementation, so the use of this
++ * request should be considered on a case-by-case basis.
++ *
++ * Note that if the transform value includes 90 or 270 degree rotation,
++ * the width of the buffer will become the surface height and the height
++ * of the buffer will become the surface width.
++ *
++ * If transform is not one of the values from the
++ * wl_output.transform enum the invalid_transform protocol error
++ * is raised.
++ */
++static inline void
++wl_surface_set_buffer_transform(struct wl_surface *wl_surface, int32_t transform)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++ WL_SURFACE_SET_BUFFER_TRANSFORM, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, transform);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * This request sets an optional scaling factor on how the compositor
++ * interprets the contents of the buffer attached to the window.
++ *
++ * Buffer scale is double-buffered state, see wl_surface.commit.
++ *
++ * A newly created surface has its buffer scale set to 1.
++ *
++ * wl_surface.set_buffer_scale changes the pending buffer scale.
++ * wl_surface.commit copies the pending buffer scale to the current one.
++ * Otherwise, the pending and current values are never changed.
++ *
++ * The purpose of this request is to allow clients to supply higher
++ * resolution buffer data for use on high resolution outputs. It is
++ * intended that you pick the same buffer scale as the scale of the
++ * output that the surface is displayed on. This means the compositor
++ * can avoid scaling when rendering the surface on that output.
++ *
++ * Note that if the scale is larger than 1, then you have to attach
++ * a buffer that is larger (by a factor of scale in each dimension)
++ * than the desired surface size.
++ *
++ * If scale is not positive the invalid_scale protocol error is
++ * raised.
++ */
++static inline void
++wl_surface_set_buffer_scale(struct wl_surface *wl_surface, int32_t scale)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++ WL_SURFACE_SET_BUFFER_SCALE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, scale);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * This request is used to describe the regions where the pending
++ * buffer is different from the current surface contents, and where
++ * the surface therefore needs to be repainted. The compositor
++ * ignores the parts of the damage that fall outside of the surface.
++ *
++ * Damage is double-buffered state, see wl_surface.commit.
++ *
++ * The damage rectangle is specified in buffer coordinates,
++ * where x and y specify the upper left corner of the damage rectangle.
++ *
++ * The initial value for pending damage is empty: no damage.
++ * wl_surface.damage_buffer adds pending damage: the new pending
++ * damage is the union of old pending damage and the given rectangle.
++ *
++ * wl_surface.commit assigns pending damage as the current damage,
++ * and clears pending damage. The server will clear the current
++ * damage as it repaints the surface.
++ *
++ * This request differs from wl_surface.damage in only one way - it
++ * takes damage in buffer coordinates instead of surface-local
++ * coordinates. While this generally is more intuitive than surface
++ * coordinates, it is especially desirable when using wp_viewport
++ * or when a drawing library (like EGL) is unaware of buffer scale
++ * and buffer transform.
++ *
++ * Note: Because buffer transformation changes and damage requests may
++ * be interleaved in the protocol stream, it is impossible to determine
++ * the actual mapping between surface and buffer damage until
++ * wl_surface.commit time. Therefore, compositors wishing to take both
++ * kinds of damage into account will have to accumulate damage from the
++ * two requests separately and only transform from one to the other
++ * after receiving the wl_surface.commit.
++ */
++static inline void
++wl_surface_damage_buffer(struct wl_surface *wl_surface, int32_t x, int32_t y, int32_t width, int32_t height)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++ WL_SURFACE_DAMAGE_BUFFER, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, x, y, width, height);
++}
++
++#ifndef WL_SEAT_CAPABILITY_ENUM
++#define WL_SEAT_CAPABILITY_ENUM
++/**
++ * @ingroup iface_wl_seat
++ * seat capability bitmask
++ *
++ * This is a bitmask of capabilities this seat has; if a member is
++ * set, then it is present on the seat.
++ */
++enum wl_seat_capability {
++ /**
++ * the seat has pointer devices
++ */
++ WL_SEAT_CAPABILITY_POINTER = 1,
++ /**
++ * the seat has one or more keyboards
++ */
++ WL_SEAT_CAPABILITY_KEYBOARD = 2,
++ /**
++ * the seat has touch devices
++ */
++ WL_SEAT_CAPABILITY_TOUCH = 4,
++};
++#endif /* WL_SEAT_CAPABILITY_ENUM */
++
++/**
++ * @ingroup iface_wl_seat
++ * @struct wl_seat_listener
++ */
++struct wl_seat_listener {
++ /**
++ * seat capabilities changed
++ *
++ * This is emitted whenever a seat gains or loses the pointer,
++ * keyboard or touch capabilities. The argument is a capability
++ * enum containing the complete set of capabilities this seat has.
++ *
++ * When the pointer capability is added, a client may create a
++ * wl_pointer object using the wl_seat.get_pointer request. This
++ * object will receive pointer events until the capability is
++ * removed in the future.
++ *
++ * When the pointer capability is removed, a client should destroy
++ * the wl_pointer objects associated with the seat where the
++ * capability was removed, using the wl_pointer.release request. No
++ * further pointer events will be received on these objects.
++ *
++ * In some compositors, if a seat regains the pointer capability
++ * and a client has a previously obtained wl_pointer object of
++ * version 4 or less, that object may start sending pointer events
++ * again. This behavior is considered a misinterpretation of the
++ * intended behavior and must not be relied upon by the client.
++ * wl_pointer objects of version 5 or later must not send events if
++ * created before the most recent event notifying the client of an
++ * added pointer capability.
++ *
++ * The above behavior also applies to wl_keyboard and wl_touch with
++ * the keyboard and touch capabilities, respectively.
++ * @param capabilities capabilities of the seat
++ */
++ void (*capabilities)(void *data,
++ struct wl_seat *wl_seat,
++ uint32_t capabilities);
++ /**
++ * unique identifier for this seat
++ *
++ * In a multiseat configuration this can be used by the client to
++ * help identify which physical devices the seat represents. Based
++ * on the seat configuration used by the compositor.
++ * @param name seat identifier
++ * @since 2
++ */
++ void (*name)(void *data,
++ struct wl_seat *wl_seat,
++ const char *name);
++};
++
++/**
++ * @ingroup iface_wl_seat
++ */
++static inline int
++wl_seat_add_listener(struct wl_seat *wl_seat,
++ const struct wl_seat_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_seat,
++ (void (**)(void)) listener, data);
++}
++
++#define WL_SEAT_GET_POINTER 0
++#define WL_SEAT_GET_KEYBOARD 1
++#define WL_SEAT_GET_TOUCH 2
++#define WL_SEAT_RELEASE 3
++
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_CAPABILITIES_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_NAME_SINCE_VERSION 2
++
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_GET_POINTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_GET_KEYBOARD_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_GET_TOUCH_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_RELEASE_SINCE_VERSION 5
++
++/** @ingroup iface_wl_seat */
++static inline void
++wl_seat_set_user_data(struct wl_seat *wl_seat, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_seat, user_data);
++}
++
++/** @ingroup iface_wl_seat */
++static inline void *
++wl_seat_get_user_data(struct wl_seat *wl_seat)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_seat);
++}
++
++static inline uint32_t
++wl_seat_get_version(struct wl_seat *wl_seat)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_seat);
++}
++
++/** @ingroup iface_wl_seat */
++static inline void
++wl_seat_destroy(struct wl_seat *wl_seat)
++{
++ wl_proxy_destroy((struct wl_proxy *) wl_seat);
++}
++
++/**
++ * @ingroup iface_wl_seat
++ *
++ * The ID provided will be initialized to the wl_pointer interface
++ * for this seat.
++ *
++ * This request only takes effect if the seat has the pointer
++ * capability, or has had the pointer capability in the past.
++ * It is a protocol violation to issue this request on a seat that has
++ * never had the pointer capability.
++ */
++static inline struct wl_pointer *
++wl_seat_get_pointer(struct wl_seat *wl_seat)
++{
++ struct wl_proxy *id;
++
++ id = wl_proxy_marshal_flags((struct wl_proxy *) wl_seat,
++ WL_SEAT_GET_POINTER, &wl_pointer_interface, wl_proxy_get_version((struct wl_proxy *) wl_seat), 0, NULL);
++
++ return (struct wl_pointer *) id;
++}
++
++/**
++ * @ingroup iface_wl_seat
++ *
++ * The ID provided will be initialized to the wl_keyboard interface
++ * for this seat.
++ *
++ * This request only takes effect if the seat has the keyboard
++ * capability, or has had the keyboard capability in the past.
++ * It is a protocol violation to issue this request on a seat that has
++ * never had the keyboard capability.
++ */
++static inline struct wl_keyboard *
++wl_seat_get_keyboard(struct wl_seat *wl_seat)
++{
++ struct wl_proxy *id;
++
++ id = wl_proxy_marshal_flags((struct wl_proxy *) wl_seat,
++ WL_SEAT_GET_KEYBOARD, &wl_keyboard_interface, wl_proxy_get_version((struct wl_proxy *) wl_seat), 0, NULL);
++
++ return (struct wl_keyboard *) id;
++}
++
++/**
++ * @ingroup iface_wl_seat
++ *
++ * The ID provided will be initialized to the wl_touch interface
++ * for this seat.
++ *
++ * This request only takes effect if the seat has the touch
++ * capability, or has had the touch capability in the past.
++ * It is a protocol violation to issue this request on a seat that has
++ * never had the touch capability.
++ */
++static inline struct wl_touch *
++wl_seat_get_touch(struct wl_seat *wl_seat)
++{
++ struct wl_proxy *id;
++
++ id = wl_proxy_marshal_flags((struct wl_proxy *) wl_seat,
++ WL_SEAT_GET_TOUCH, &wl_touch_interface, wl_proxy_get_version((struct wl_proxy *) wl_seat), 0, NULL);
++
++ return (struct wl_touch *) id;
++}
++
++/**
++ * @ingroup iface_wl_seat
++ *
++ * Using this request a client can tell the server that it is not going to
++ * use the seat object anymore.
++ */
++static inline void
++wl_seat_release(struct wl_seat *wl_seat)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_seat,
++ WL_SEAT_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_seat), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#ifndef WL_POINTER_ERROR_ENUM
++#define WL_POINTER_ERROR_ENUM
++enum wl_pointer_error {
++ /**
++ * given wl_surface has another role
++ */
++ WL_POINTER_ERROR_ROLE = 0,
++};
++#endif /* WL_POINTER_ERROR_ENUM */
++
++#ifndef WL_POINTER_BUTTON_STATE_ENUM
++#define WL_POINTER_BUTTON_STATE_ENUM
++/**
++ * @ingroup iface_wl_pointer
++ * physical button state
++ *
++ * Describes the physical state of a button that produced the button
++ * event.
++ */
++enum wl_pointer_button_state {
++ /**
++ * the button is not pressed
++ */
++ WL_POINTER_BUTTON_STATE_RELEASED = 0,
++ /**
++ * the button is pressed
++ */
++ WL_POINTER_BUTTON_STATE_PRESSED = 1,
++};
++#endif /* WL_POINTER_BUTTON_STATE_ENUM */
++
++#ifndef WL_POINTER_AXIS_ENUM
++#define WL_POINTER_AXIS_ENUM
++/**
++ * @ingroup iface_wl_pointer
++ * axis types
++ *
++ * Describes the axis types of scroll events.
++ */
++enum wl_pointer_axis {
++ /**
++ * vertical axis
++ */
++ WL_POINTER_AXIS_VERTICAL_SCROLL = 0,
++ /**
++ * horizontal axis
++ */
++ WL_POINTER_AXIS_HORIZONTAL_SCROLL = 1,
++};
++#endif /* WL_POINTER_AXIS_ENUM */
++
++#ifndef WL_POINTER_AXIS_SOURCE_ENUM
++#define WL_POINTER_AXIS_SOURCE_ENUM
++/**
++ * @ingroup iface_wl_pointer
++ * axis source types
++ *
++ * Describes the source types for axis events. This indicates to the
++ * client how an axis event was physically generated; a client may
++ * adjust the user interface accordingly. For example, scroll events
++ * from a "finger" source may be in a smooth coordinate space with
++ * kinetic scrolling whereas a "wheel" source may be in discrete steps
++ * of a number of lines.
++ */
++enum wl_pointer_axis_source {
++ /**
++ * a physical wheel rotation
++ */
++ WL_POINTER_AXIS_SOURCE_WHEEL = 0,
++ /**
++ * finger on a touch surface
++ */
++ WL_POINTER_AXIS_SOURCE_FINGER = 1,
++ /**
++ * continuous coordinate space
++ *
++ * A device generating events in a continuous coordinate space,
++ * but using something other than a finger. One example for this
++ * source is button-based scrolling where the vertical motion of a
++ * device is converted to scroll events while a button is held
++ * down.
++ */
++ WL_POINTER_AXIS_SOURCE_CONTINUOUS = 2,
++ /**
++ * a physical wheel tilt
++ *
++ * Indicates that the actual device is a wheel but the scroll
++ * event is not caused by a rotation but a (usually sideways) tilt
++ * of the wheel.
++ * @since 6
++ */
++ WL_POINTER_AXIS_SOURCE_WHEEL_TILT = 3,
++};
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION 6
++#endif /* WL_POINTER_AXIS_SOURCE_ENUM */
++
++/**
++ * @ingroup iface_wl_pointer
++ * @struct wl_pointer_listener
++ */
++struct wl_pointer_listener {
++ /**
++ * enter event
++ *
++ * Notification that this seat's pointer is focused on a certain
++ * surface.
++ *
++ * When a seat's focus enters a surface, the pointer image is
++ * undefined and a client should respond to this event by setting
++ * an appropriate pointer image with the set_cursor request.
++ * @param serial serial number of the enter event
++ * @param surface surface entered by the pointer
++ * @param surface_x surface-local x coordinate
++ * @param surface_y surface-local y coordinate
++ */
++ void (*enter)(void *data,
++ struct wl_pointer *wl_pointer,
++ uint32_t serial,
++ struct wl_surface *surface,
++ wl_fixed_t surface_x,
++ wl_fixed_t surface_y);
++ /**
++ * leave event
++ *
++ * Notification that this seat's pointer is no longer focused on
++ * a certain surface.
++ *
++ * The leave notification is sent before the enter notification for
++ * the new focus.
++ * @param serial serial number of the leave event
++ * @param surface surface left by the pointer
++ */
++ void (*leave)(void *data,
++ struct wl_pointer *wl_pointer,
++ uint32_t serial,
++ struct wl_surface *surface);
++ /**
++ * pointer motion event
++ *
++ * Notification of pointer location change. The arguments
++ * surface_x and surface_y are the location relative to the focused
++ * surface.
++ * @param time timestamp with millisecond granularity
++ * @param surface_x surface-local x coordinate
++ * @param surface_y surface-local y coordinate
++ */
++ void (*motion)(void *data,
++ struct wl_pointer *wl_pointer,
++ uint32_t time,
++ wl_fixed_t surface_x,
++ wl_fixed_t surface_y);
++ /**
++ * pointer button event
++ *
++ * Mouse button click and release notifications.
++ *
++ * The location of the click is given by the last motion or enter
++ * event. The time argument is a timestamp with millisecond
++ * granularity, with an undefined base.
++ *
++ * The button is a button code as defined in the Linux kernel's
++ * linux/input-event-codes.h header file, e.g. BTN_LEFT.
++ *
++ * Any 16-bit button code value is reserved for future additions to
++ * the kernel's event code list. All other button codes above
++ * 0xFFFF are currently undefined but may be used in future
++ * versions of this protocol.
++ * @param serial serial number of the button event
++ * @param time timestamp with millisecond granularity
++ * @param button button that produced the event
++ * @param state physical state of the button
++ */
++ void (*button)(void *data,
++ struct wl_pointer *wl_pointer,
++ uint32_t serial,
++ uint32_t time,
++ uint32_t button,
++ uint32_t state);
++ /**
++ * axis event
++ *
++ * Scroll and other axis notifications.
++ *
++ * For scroll events (vertical and horizontal scroll axes), the
++ * value parameter is the length of a vector along the specified
++ * axis in a coordinate space identical to those of motion events,
++ * representing a relative movement along the specified axis.
++ *
++ * For devices that support movements non-parallel to axes multiple
++ * axis events will be emitted.
++ *
++ * When applicable, for example for touch pads, the server can
++ * choose to emit scroll events where the motion vector is
++ * equivalent to a motion event vector.
++ *
++ * When applicable, a client can transform its content relative to
++ * the scroll distance.
++ * @param time timestamp with millisecond granularity
++ * @param axis axis type
++ * @param value length of vector in surface-local coordinate space
++ */
++ void (*axis)(void *data,
++ struct wl_pointer *wl_pointer,
++ uint32_t time,
++ uint32_t axis,
++ wl_fixed_t value);
++ /**
++ * end of a pointer event sequence
++ *
++ * Indicates the end of a set of events that logically belong
++ * together. A client is expected to accumulate the data in all
++ * events within the frame before proceeding.
++ *
++ * All wl_pointer events before a wl_pointer.frame event belong
++ * logically together. For example, in a diagonal scroll motion the
++ * compositor will send an optional wl_pointer.axis_source event,
++ * two wl_pointer.axis events (horizontal and vertical) and finally
++ * a wl_pointer.frame event. The client may use this information to
++ * calculate a diagonal vector for scrolling.
++ *
++ * When multiple wl_pointer.axis events occur within the same
++ * frame, the motion vector is the combined motion of all events.
++ * When a wl_pointer.axis and a wl_pointer.axis_stop event occur
++ * within the same frame, this indicates that axis movement in one
++ * axis has stopped but continues in the other axis. When multiple
++ * wl_pointer.axis_stop events occur within the same frame, this
++ * indicates that these axes stopped in the same instance.
++ *
++ * A wl_pointer.frame event is sent for every logical event group,
++ * even if the group only contains a single wl_pointer event.
++ * Specifically, a client may get a sequence: motion, frame,
++ * button, frame, axis, frame, axis_stop, frame.
++ *
++ * The wl_pointer.enter and wl_pointer.leave events are logical
++ * events generated by the compositor and not the hardware. These
++ * events are also grouped by a wl_pointer.frame. When a pointer
++ * moves from one surface to another, a compositor should group the
++ * wl_pointer.leave event within the same wl_pointer.frame.
++ * However, a client must not rely on wl_pointer.leave and
++ * wl_pointer.enter being in the same wl_pointer.frame.
++ * Compositor-specific policies may require the wl_pointer.leave
++ * and wl_pointer.enter event being split across multiple
++ * wl_pointer.frame groups.
++ * @since 5
++ */
++ void (*frame)(void *data,
++ struct wl_pointer *wl_pointer);
++ /**
++ * axis source event
++ *
++ * Source information for scroll and other axes.
++ *
++ * This event does not occur on its own. It is sent before a
++ * wl_pointer.frame event and carries the source information for
++ * all events within that frame.
++ *
++ * The source specifies how this event was generated. If the source
++ * is wl_pointer.axis_source.finger, a wl_pointer.axis_stop event
++ * will be sent when the user lifts the finger off the device.
++ *
++ * If the source is wl_pointer.axis_source.wheel,
++ * wl_pointer.axis_source.wheel_tilt or
++ * wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event
++ * may or may not be sent. Whether a compositor sends an axis_stop
++ * event for these sources is hardware-specific and
++ * implementation-dependent; clients must not rely on receiving an
++ * axis_stop event for these scroll sources and should treat scroll
++ * sequences from these scroll sources as unterminated by default.
++ *
++ * This event is optional. If the source is unknown for a
++ * particular axis event sequence, no event is sent. Only one
++ * wl_pointer.axis_source event is permitted per frame.
++ *
++ * The order of wl_pointer.axis_discrete and wl_pointer.axis_source
++ * is not guaranteed.
++ * @param axis_source source of the axis event
++ * @since 5
++ */
++ void (*axis_source)(void *data,
++ struct wl_pointer *wl_pointer,
++ uint32_t axis_source);
++ /**
++ * axis stop event
++ *
++ * Stop notification for scroll and other axes.
++ *
++ * For some wl_pointer.axis_source types, a wl_pointer.axis_stop
++ * event is sent to notify a client that the axis sequence has
++ * terminated. This enables the client to implement kinetic
++ * scrolling. See the wl_pointer.axis_source documentation for
++ * information on when this event may be generated.
++ *
++ * Any wl_pointer.axis events with the same axis_source after this
++ * event should be considered as the start of a new axis motion.
++ *
++ * The timestamp is to be interpreted identical to the timestamp in
++ * the wl_pointer.axis event. The timestamp value may be the same
++ * as a preceding wl_pointer.axis event.
++ * @param time timestamp with millisecond granularity
++ * @param axis the axis stopped with this event
++ * @since 5
++ */
++ void (*axis_stop)(void *data,
++ struct wl_pointer *wl_pointer,
++ uint32_t time,
++ uint32_t axis);
++ /**
++ * axis click event
++ *
++ * Discrete step information for scroll and other axes.
++ *
++ * This event carries the axis value of the wl_pointer.axis event
++ * in discrete steps (e.g. mouse wheel clicks).
++ *
++ * This event does not occur on its own, it is coupled with a
++ * wl_pointer.axis event that represents this axis value on a
++ * continuous scale. The protocol guarantees that each
++ * axis_discrete event is always followed by exactly one axis event
++ * with the same axis number within the same wl_pointer.frame. Note
++ * that the protocol allows for other events to occur between the
++ * axis_discrete and its coupled axis event, including other
++ * axis_discrete or axis events.
++ *
++ * This event is optional; continuous scrolling devices like
++ * two-finger scrolling on touchpads do not have discrete steps and
++ * do not generate this event.
++ *
++ * The discrete value carries the directional information. e.g. a
++ * value of -2 is two steps towards the negative direction of this
++ * axis.
++ *
++ * The axis number is identical to the axis number in the
++ * associated axis event.
++ *
++ * The order of wl_pointer.axis_discrete and wl_pointer.axis_source
++ * is not guaranteed.
++ * @param axis axis type
++ * @param discrete number of steps
++ * @since 5
++ */
++ void (*axis_discrete)(void *data,
++ struct wl_pointer *wl_pointer,
++ uint32_t axis,
++ int32_t discrete);
++};
++
++/**
++ * @ingroup iface_wl_pointer
++ */
++static inline int
++wl_pointer_add_listener(struct wl_pointer *wl_pointer,
++ const struct wl_pointer_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_pointer,
++ (void (**)(void)) listener, data);
++}
++
++#define WL_POINTER_SET_CURSOR 0
++#define WL_POINTER_RELEASE 1
++
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_LEAVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_MOTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_BUTTON_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_FRAME_SINCE_VERSION 5
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_SOURCE_SINCE_VERSION 5
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_STOP_SINCE_VERSION 5
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_DISCRETE_SINCE_VERSION 5
++
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_SET_CURSOR_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_RELEASE_SINCE_VERSION 3
++
++/** @ingroup iface_wl_pointer */
++static inline void
++wl_pointer_set_user_data(struct wl_pointer *wl_pointer, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_pointer, user_data);
++}
++
++/** @ingroup iface_wl_pointer */
++static inline void *
++wl_pointer_get_user_data(struct wl_pointer *wl_pointer)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_pointer);
++}
++
++static inline uint32_t
++wl_pointer_get_version(struct wl_pointer *wl_pointer)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_pointer);
++}
++
++/** @ingroup iface_wl_pointer */
++static inline void
++wl_pointer_destroy(struct wl_pointer *wl_pointer)
++{
++ wl_proxy_destroy((struct wl_proxy *) wl_pointer);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ *
++ * Set the pointer surface, i.e., the surface that contains the
++ * pointer image (cursor). This request gives the surface the role
++ * of a cursor. If the surface already has another role, it raises
++ * a protocol error.
++ *
++ * The cursor actually changes only if the pointer
++ * focus for this device is one of the requesting client's surfaces
++ * or the surface parameter is the current pointer surface. If
++ * there was a previous surface set with this request it is
++ * replaced. If surface is NULL, the pointer image is hidden.
++ *
++ * The parameters hotspot_x and hotspot_y define the position of
++ * the pointer surface relative to the pointer location. Its
++ * top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
++ * where (x, y) are the coordinates of the pointer location, in
++ * surface-local coordinates.
++ *
++ * On surface.attach requests to the pointer surface, hotspot_x
++ * and hotspot_y are decremented by the x and y parameters
++ * passed to the request. Attach must be confirmed by
++ * wl_surface.commit as usual.
++ *
++ * The hotspot can also be updated by passing the currently set
++ * pointer surface to this request with new values for hotspot_x
++ * and hotspot_y.
++ *
++ * The current and pending input regions of the wl_surface are
++ * cleared, and wl_surface.set_input_region is ignored until the
++ * wl_surface is no longer used as the cursor. When the use as a
++ * cursor ends, the current and pending input regions become
++ * undefined, and the wl_surface is unmapped.
++ */
++static inline void
++wl_pointer_set_cursor(struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, int32_t hotspot_x, int32_t hotspot_y)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_pointer,
++ WL_POINTER_SET_CURSOR, NULL, wl_proxy_get_version((struct wl_proxy *) wl_pointer), 0, serial, surface, hotspot_x, hotspot_y);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ *
++ * Using this request a client can tell the server that it is not going to
++ * use the pointer object anymore.
++ *
++ * This request destroys the pointer proxy object, so clients must not call
++ * wl_pointer_destroy() after using this request.
++ */
++static inline void
++wl_pointer_release(struct wl_pointer *wl_pointer)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_pointer,
++ WL_POINTER_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_pointer), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#ifndef WL_KEYBOARD_KEYMAP_FORMAT_ENUM
++#define WL_KEYBOARD_KEYMAP_FORMAT_ENUM
++/**
++ * @ingroup iface_wl_keyboard
++ * keyboard mapping format
++ *
++ * This specifies the format of the keymap provided to the
++ * client with the wl_keyboard.keymap event.
++ */
++enum wl_keyboard_keymap_format {
++ /**
++ * no keymap; client must understand how to interpret the raw keycode
++ */
++ WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP = 0,
++ /**
++ * libxkbcommon compatible; to determine the xkb keycode, clients must add 8 to the key event keycode
++ */
++ WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 = 1,
++};
++#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM */
++
++#ifndef WL_KEYBOARD_KEY_STATE_ENUM
++#define WL_KEYBOARD_KEY_STATE_ENUM
++/**
++ * @ingroup iface_wl_keyboard
++ * physical key state
++ *
++ * Describes the physical state of a key that produced the key event.
++ */
++enum wl_keyboard_key_state {
++ /**
++ * key is not pressed
++ */
++ WL_KEYBOARD_KEY_STATE_RELEASED = 0,
++ /**
++ * key is pressed
++ */
++ WL_KEYBOARD_KEY_STATE_PRESSED = 1,
++};
++#endif /* WL_KEYBOARD_KEY_STATE_ENUM */
++
++/**
++ * @ingroup iface_wl_keyboard
++ * @struct wl_keyboard_listener
++ */
++struct wl_keyboard_listener {
++ /**
++ * keyboard mapping
++ *
++ * This event provides a file descriptor to the client which can
++ * be memory-mapped to provide a keyboard mapping description.
++ * @param format keymap format
++ * @param fd keymap file descriptor
++ * @param size keymap size, in bytes
++ */
++ void (*keymap)(void *data,
++ struct wl_keyboard *wl_keyboard,
++ uint32_t format,
++ int32_t fd,
++ uint32_t size);
++ /**
++ * enter event
++ *
++ * Notification that this seat's keyboard focus is on a certain
++ * surface.
++ * @param serial serial number of the enter event
++ * @param surface surface gaining keyboard focus
++ * @param keys the currently pressed keys
++ */
++ void (*enter)(void *data,
++ struct wl_keyboard *wl_keyboard,
++ uint32_t serial,
++ struct wl_surface *surface,
++ struct wl_array *keys);
++ /**
++ * leave event
++ *
++ * Notification that this seat's keyboard focus is no longer on a
++ * certain surface.
++ *
++ * The leave notification is sent before the enter notification for
++ * the new focus.
++ * @param serial serial number of the leave event
++ * @param surface surface that lost keyboard focus
++ */
++ void (*leave)(void *data,
++ struct wl_keyboard *wl_keyboard,
++ uint32_t serial,
++ struct wl_surface *surface);
++ /**
++ * key event
++ *
++ * A key was pressed or released. The time argument is a
++ * timestamp with millisecond granularity, with an undefined base.
++ * @param serial serial number of the key event
++ * @param time timestamp with millisecond granularity
++ * @param key key that produced the event
++ * @param state physical state of the key
++ */
++ void (*key)(void *data,
++ struct wl_keyboard *wl_keyboard,
++ uint32_t serial,
++ uint32_t time,
++ uint32_t key,
++ uint32_t state);
++ /**
++ * modifier and group state
++ *
++ * Notifies clients that the modifier and/or group state has
++ * changed, and it should update its local state.
++ * @param serial serial number of the modifiers event
++ * @param mods_depressed depressed modifiers
++ * @param mods_latched latched modifiers
++ * @param mods_locked locked modifiers
++ * @param group keyboard layout
++ */
++ void (*modifiers)(void *data,
++ struct wl_keyboard *wl_keyboard,
++ uint32_t serial,
++ uint32_t mods_depressed,
++ uint32_t mods_latched,
++ uint32_t mods_locked,
++ uint32_t group);
++ /**
++ * repeat rate and delay
++ *
++ * Informs the client about the keyboard's repeat rate and delay.
++ *
++ * This event is sent as soon as the wl_keyboard object has been
++ * created, and is guaranteed to be received by the client before
++ * any key press event.
++ *
++ * Negative values for either rate or delay are illegal. A rate of
++ * zero will disable any repeating (regardless of the value of
++ * delay).
++ *
++ * This event can be sent later on as well with a new value if
++ * necessary, so clients should continue listening for the event
++ * past the creation of wl_keyboard.
++ * @param rate the rate of repeating keys in characters per second
++ * @param delay delay in milliseconds since key down until repeating starts
++ * @since 4
++ */
++ void (*repeat_info)(void *data,
++ struct wl_keyboard *wl_keyboard,
++ int32_t rate,
++ int32_t delay);
++};
++
++/**
++ * @ingroup iface_wl_keyboard
++ */
++static inline int
++wl_keyboard_add_listener(struct wl_keyboard *wl_keyboard,
++ const struct wl_keyboard_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_keyboard,
++ (void (**)(void)) listener, data);
++}
++
++#define WL_KEYBOARD_RELEASE 0
++
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_KEYMAP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_LEAVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_KEY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_MODIFIERS_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION 4
++
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_RELEASE_SINCE_VERSION 3
++
++/** @ingroup iface_wl_keyboard */
++static inline void
++wl_keyboard_set_user_data(struct wl_keyboard *wl_keyboard, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_keyboard, user_data);
++}
++
++/** @ingroup iface_wl_keyboard */
++static inline void *
++wl_keyboard_get_user_data(struct wl_keyboard *wl_keyboard)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_keyboard);
++}
++
++static inline uint32_t
++wl_keyboard_get_version(struct wl_keyboard *wl_keyboard)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_keyboard);
++}
++
++/** @ingroup iface_wl_keyboard */
++static inline void
++wl_keyboard_destroy(struct wl_keyboard *wl_keyboard)
++{
++ wl_proxy_destroy((struct wl_proxy *) wl_keyboard);
++}
++
++/**
++ * @ingroup iface_wl_keyboard
++ */
++static inline void
++wl_keyboard_release(struct wl_keyboard *wl_keyboard)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_keyboard,
++ WL_KEYBOARD_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_keyboard), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * @struct wl_touch_listener
++ */
++struct wl_touch_listener {
++ /**
++ * touch down event and beginning of a touch sequence
++ *
++ * A new touch point has appeared on the surface. This touch
++ * point is assigned a unique ID. Future events from this touch
++ * point reference this ID. The ID ceases to be valid after a touch
++ * up event and may be reused in the future.
++ * @param serial serial number of the touch down event
++ * @param time timestamp with millisecond granularity
++ * @param surface surface touched
++ * @param id the unique ID of this touch point
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ */
++ void (*down)(void *data,
++ struct wl_touch *wl_touch,
++ uint32_t serial,
++ uint32_t time,
++ struct wl_surface *surface,
++ int32_t id,
++ wl_fixed_t x,
++ wl_fixed_t y);
++ /**
++ * end of a touch event sequence
++ *
++ * The touch point has disappeared. No further events will be
++ * sent for this touch point and the touch point's ID is released
++ * and may be reused in a future touch down event.
++ * @param serial serial number of the touch up event
++ * @param time timestamp with millisecond granularity
++ * @param id the unique ID of this touch point
++ */
++ void (*up)(void *data,
++ struct wl_touch *wl_touch,
++ uint32_t serial,
++ uint32_t time,
++ int32_t id);
++ /**
++ * update of touch point coordinates
++ *
++ * A touch point has changed coordinates.
++ * @param time timestamp with millisecond granularity
++ * @param id the unique ID of this touch point
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ */
++ void (*motion)(void *data,
++ struct wl_touch *wl_touch,
++ uint32_t time,
++ int32_t id,
++ wl_fixed_t x,
++ wl_fixed_t y);
++ /**
++ * end of touch frame event
++ *
++ * Indicates the end of a set of events that logically belong
++ * together. A client is expected to accumulate the data in all
++ * events within the frame before proceeding.
++ *
++ * A wl_touch.frame terminates at least one event but otherwise no
++ * guarantee is provided about the set of events within a frame. A
++ * client must assume that any state not updated in a frame is
++ * unchanged from the previously known state.
++ */
++ void (*frame)(void *data,
++ struct wl_touch *wl_touch);
++ /**
++ * touch session cancelled
++ *
++ * Sent if the compositor decides the touch stream is a global
++ * gesture. No further events are sent to the clients from that
++ * particular gesture. Touch cancellation applies to all touch
++ * points currently active on this client's surface. The client is
++ * responsible for finalizing the touch points, future touch points
++ * on this surface may reuse the touch point ID.
++ */
++ void (*cancel)(void *data,
++ struct wl_touch *wl_touch);
++ /**
++ * update shape of touch point
++ *
++ * Sent when a touchpoint has changed its shape.
++ *
++ * This event does not occur on its own. It is sent before a
++ * wl_touch.frame event and carries the new shape information for
++ * any previously reported, or new touch points of that frame.
++ *
++ * Other events describing the touch point such as wl_touch.down,
++ * wl_touch.motion or wl_touch.orientation may be sent within the
++ * same wl_touch.frame. A client should treat these events as a
++ * single logical touch point update. The order of wl_touch.shape,
++ * wl_touch.orientation and wl_touch.motion is not guaranteed. A
++ * wl_touch.down event is guaranteed to occur before the first
++ * wl_touch.shape event for this touch ID but both events may occur
++ * within the same wl_touch.frame.
++ *
++ * A touchpoint shape is approximated by an ellipse through the
++ * major and minor axis length. The major axis length describes the
++ * longer diameter of the ellipse, while the minor axis length
++ * describes the shorter diameter. Major and minor are orthogonal
++ * and both are specified in surface-local coordinates. The center
++ * of the ellipse is always at the touchpoint location as reported
++ * by wl_touch.down or wl_touch.move.
++ *
++ * This event is only sent by the compositor if the touch device
++ * supports shape reports. The client has to make reasonable
++ * assumptions about the shape if it did not receive this event.
++ * @param id the unique ID of this touch point
++ * @param major length of the major axis in surface-local coordinates
++ * @param minor length of the minor axis in surface-local coordinates
++ * @since 6
++ */
++ void (*shape)(void *data,
++ struct wl_touch *wl_touch,
++ int32_t id,
++ wl_fixed_t major,
++ wl_fixed_t minor);
++ /**
++ * update orientation of touch point
++ *
++ * Sent when a touchpoint has changed its orientation.
++ *
++ * This event does not occur on its own. It is sent before a
++ * wl_touch.frame event and carries the new shape information for
++ * any previously reported, or new touch points of that frame.
++ *
++ * Other events describing the touch point such as wl_touch.down,
++ * wl_touch.motion or wl_touch.shape may be sent within the same
++ * wl_touch.frame. A client should treat these events as a single
++ * logical touch point update. The order of wl_touch.shape,
++ * wl_touch.orientation and wl_touch.motion is not guaranteed. A
++ * wl_touch.down event is guaranteed to occur before the first
++ * wl_touch.orientation event for this touch ID but both events may
++ * occur within the same wl_touch.frame.
++ *
++ * The orientation describes the clockwise angle of a touchpoint's
++ * major axis to the positive surface y-axis and is normalized to
++ * the -180 to +180 degree range. The granularity of orientation
++ * depends on the touch device, some devices only support binary
++ * rotation values between 0 and 90 degrees.
++ *
++ * This event is only sent by the compositor if the touch device
++ * supports orientation reports.
++ * @param id the unique ID of this touch point
++ * @param orientation angle between major axis and positive surface y-axis in degrees
++ * @since 6
++ */
++ void (*orientation)(void *data,
++ struct wl_touch *wl_touch,
++ int32_t id,
++ wl_fixed_t orientation);
++};
++
++/**
++ * @ingroup iface_wl_touch
++ */
++static inline int
++wl_touch_add_listener(struct wl_touch *wl_touch,
++ const struct wl_touch_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_touch,
++ (void (**)(void)) listener, data);
++}
++
++#define WL_TOUCH_RELEASE 0
++
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_DOWN_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_UP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_MOTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_FRAME_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_CANCEL_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_SHAPE_SINCE_VERSION 6
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_ORIENTATION_SINCE_VERSION 6
++
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_RELEASE_SINCE_VERSION 3
++
++/** @ingroup iface_wl_touch */
++static inline void
++wl_touch_set_user_data(struct wl_touch *wl_touch, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_touch, user_data);
++}
++
++/** @ingroup iface_wl_touch */
++static inline void *
++wl_touch_get_user_data(struct wl_touch *wl_touch)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_touch);
++}
++
++static inline uint32_t
++wl_touch_get_version(struct wl_touch *wl_touch)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_touch);
++}
++
++/** @ingroup iface_wl_touch */
++static inline void
++wl_touch_destroy(struct wl_touch *wl_touch)
++{
++ wl_proxy_destroy((struct wl_proxy *) wl_touch);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ */
++static inline void
++wl_touch_release(struct wl_touch *wl_touch)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_touch,
++ WL_TOUCH_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_touch), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#ifndef WL_OUTPUT_SUBPIXEL_ENUM
++#define WL_OUTPUT_SUBPIXEL_ENUM
++/**
++ * @ingroup iface_wl_output
++ * subpixel geometry information
++ *
++ * This enumeration describes how the physical
++ * pixels on an output are laid out.
++ */
++enum wl_output_subpixel {
++ /**
++ * unknown geometry
++ */
++ WL_OUTPUT_SUBPIXEL_UNKNOWN = 0,
++ /**
++ * no geometry
++ */
++ WL_OUTPUT_SUBPIXEL_NONE = 1,
++ /**
++ * horizontal RGB
++ */
++ WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB = 2,
++ /**
++ * horizontal BGR
++ */
++ WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR = 3,
++ /**
++ * vertical RGB
++ */
++ WL_OUTPUT_SUBPIXEL_VERTICAL_RGB = 4,
++ /**
++ * vertical BGR
++ */
++ WL_OUTPUT_SUBPIXEL_VERTICAL_BGR = 5,
++};
++#endif /* WL_OUTPUT_SUBPIXEL_ENUM */
++
++#ifndef WL_OUTPUT_TRANSFORM_ENUM
++#define WL_OUTPUT_TRANSFORM_ENUM
++/**
++ * @ingroup iface_wl_output
++ * transform from framebuffer to output
++ *
++ * This describes the transform that a compositor will apply to a
++ * surface to compensate for the rotation or mirroring of an
++ * output device.
++ *
++ * The flipped values correspond to an initial flip around a
++ * vertical axis followed by rotation.
++ *
++ * The purpose is mainly to allow clients to render accordingly and
++ * tell the compositor, so that for fullscreen surfaces, the
++ * compositor will still be able to scan out directly from client
++ * surfaces.
++ */
++enum wl_output_transform {
++ /**
++ * no transform
++ */
++ WL_OUTPUT_TRANSFORM_NORMAL = 0,
++ /**
++ * 90 degrees counter-clockwise
++ */
++ WL_OUTPUT_TRANSFORM_90 = 1,
++ /**
++ * 180 degrees counter-clockwise
++ */
++ WL_OUTPUT_TRANSFORM_180 = 2,
++ /**
++ * 270 degrees counter-clockwise
++ */
++ WL_OUTPUT_TRANSFORM_270 = 3,
++ /**
++ * 180 degree flip around a vertical axis
++ */
++ WL_OUTPUT_TRANSFORM_FLIPPED = 4,
++ /**
++ * flip and rotate 90 degrees counter-clockwise
++ */
++ WL_OUTPUT_TRANSFORM_FLIPPED_90 = 5,
++ /**
++ * flip and rotate 180 degrees counter-clockwise
++ */
++ WL_OUTPUT_TRANSFORM_FLIPPED_180 = 6,
++ /**
++ * flip and rotate 270 degrees counter-clockwise
++ */
++ WL_OUTPUT_TRANSFORM_FLIPPED_270 = 7,
++};
++#endif /* WL_OUTPUT_TRANSFORM_ENUM */
++
++#ifndef WL_OUTPUT_MODE_ENUM
++#define WL_OUTPUT_MODE_ENUM
++/**
++ * @ingroup iface_wl_output
++ * mode information
++ *
++ * These flags describe properties of an output mode.
++ * They are used in the flags bitfield of the mode event.
++ */
++enum wl_output_mode {
++ /**
++ * indicates this is the current mode
++ */
++ WL_OUTPUT_MODE_CURRENT = 0x1,
++ /**
++ * indicates this is the preferred mode
++ */
++ WL_OUTPUT_MODE_PREFERRED = 0x2,
++};
++#endif /* WL_OUTPUT_MODE_ENUM */
++
++/**
++ * @ingroup iface_wl_output
++ * @struct wl_output_listener
++ */
++struct wl_output_listener {
++ /**
++ * properties of the output
++ *
++ * The geometry event describes geometric properties of the
++ * output. The event is sent when binding to the output object and
++ * whenever any of the properties change.
++ * @param x x position within the global compositor space
++ * @param y y position within the global compositor space
++ * @param physical_width width in millimeters of the output
++ * @param physical_height height in millimeters of the output
++ * @param subpixel subpixel orientation of the output
++ * @param make textual description of the manufacturer
++ * @param model textual description of the model
++ * @param transform transform that maps framebuffer to output
++ */
++ void (*geometry)(void *data,
++ struct wl_output *wl_output,
++ int32_t x,
++ int32_t y,
++ int32_t physical_width,
++ int32_t physical_height,
++ int32_t subpixel,
++ const char *make,
++ const char *model,
++ int32_t transform);
++ /**
++ * advertise available modes for the output
++ *
++ * The mode event describes an available mode for the output.
++ *
++ * The event is sent when binding to the output object and there
++ * will always be one mode, the current mode. The event is sent
++ * again if an output changes mode, for the mode that is now
++ * current. In other words, the current mode is always the last
++ * mode that was received with the current flag set.
++ *
++ * The size of a mode is given in physical hardware units of the
++ * output device. This is not necessarily the same as the output
++ * size in the global compositor space. For instance, the output
++ * may be scaled, as described in wl_output.scale, or transformed,
++ * as described in wl_output.transform.
++ * @param flags bitfield of mode flags
++ * @param width width of the mode in hardware units
++ * @param height height of the mode in hardware units
++ * @param refresh vertical refresh rate in mHz
++ */
++ void (*mode)(void *data,
++ struct wl_output *wl_output,
++ uint32_t flags,
++ int32_t width,
++ int32_t height,
++ int32_t refresh);
++ /**
++ * sent all information about output
++ *
++ * This event is sent after all other properties have been sent
++ * after binding to the output object and after any other property
++ * changes done after that. This allows changes to the output
++ * properties to be seen as atomic, even if they happen via
++ * multiple events.
++ * @since 2
++ */
++ void (*done)(void *data,
++ struct wl_output *wl_output);
++ /**
++ * output scaling properties
++ *
++ * This event contains scaling geometry information that is not
++ * in the geometry event. It may be sent after binding the output
++ * object or if the output scale changes later. If it is not sent,
++ * the client should assume a scale of 1.
++ *
++ * A scale larger than 1 means that the compositor will
++ * automatically scale surface buffers by this amount when
++ * rendering. This is used for very high resolution displays where
++ * applications rendering at the native resolution would be too
++ * small to be legible.
++ *
++ * It is intended that scaling aware clients track the current
++ * output of a surface, and if it is on a scaled output it should
++ * use wl_surface.set_buffer_scale with the scale of the output.
++ * That way the compositor can avoid scaling the surface, and the
++ * client can supply a higher detail image.
++ * @param factor scaling factor of output
++ * @since 2
++ */
++ void (*scale)(void *data,
++ struct wl_output *wl_output,
++ int32_t factor);
++};
++
++/**
++ * @ingroup iface_wl_output
++ */
++static inline int
++wl_output_add_listener(struct wl_output *wl_output,
++ const struct wl_output_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) wl_output,
++ (void (**)(void)) listener, data);
++}
++
++#define WL_OUTPUT_RELEASE 0
++
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_GEOMETRY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_MODE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_DONE_SINCE_VERSION 2
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_SCALE_SINCE_VERSION 2
++
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_RELEASE_SINCE_VERSION 3
++
++/** @ingroup iface_wl_output */
++static inline void
++wl_output_set_user_data(struct wl_output *wl_output, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_output, user_data);
++}
++
++/** @ingroup iface_wl_output */
++static inline void *
++wl_output_get_user_data(struct wl_output *wl_output)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_output);
++}
++
++static inline uint32_t
++wl_output_get_version(struct wl_output *wl_output)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_output);
++}
++
++/** @ingroup iface_wl_output */
++static inline void
++wl_output_destroy(struct wl_output *wl_output)
++{
++ wl_proxy_destroy((struct wl_proxy *) wl_output);
++}
++
++/**
++ * @ingroup iface_wl_output
++ *
++ * Using this request a client can tell the server that it is not going to
++ * use the output object anymore.
++ */
++static inline void
++wl_output_release(struct wl_output *wl_output)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_output,
++ WL_OUTPUT_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_output), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#define WL_REGION_DESTROY 0
++#define WL_REGION_ADD 1
++#define WL_REGION_SUBTRACT 2
++
++
++/**
++ * @ingroup iface_wl_region
++ */
++#define WL_REGION_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_region
++ */
++#define WL_REGION_ADD_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_region
++ */
++#define WL_REGION_SUBTRACT_SINCE_VERSION 1
++
++/** @ingroup iface_wl_region */
++static inline void
++wl_region_set_user_data(struct wl_region *wl_region, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_region, user_data);
++}
++
++/** @ingroup iface_wl_region */
++static inline void *
++wl_region_get_user_data(struct wl_region *wl_region)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_region);
++}
++
++static inline uint32_t
++wl_region_get_version(struct wl_region *wl_region)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_region);
++}
++
++/**
++ * @ingroup iface_wl_region
++ *
++ * Destroy the region. This will invalidate the object ID.
++ */
++static inline void
++wl_region_destroy(struct wl_region *wl_region)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_region,
++ WL_REGION_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_region), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_region
++ *
++ * Add the specified rectangle to the region.
++ */
++static inline void
++wl_region_add(struct wl_region *wl_region, int32_t x, int32_t y, int32_t width, int32_t height)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_region,
++ WL_REGION_ADD, NULL, wl_proxy_get_version((struct wl_proxy *) wl_region), 0, x, y, width, height);
++}
++
++/**
++ * @ingroup iface_wl_region
++ *
++ * Subtract the specified rectangle from the region.
++ */
++static inline void
++wl_region_subtract(struct wl_region *wl_region, int32_t x, int32_t y, int32_t width, int32_t height)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_region,
++ WL_REGION_SUBTRACT, NULL, wl_proxy_get_version((struct wl_proxy *) wl_region), 0, x, y, width, height);
++}
++
++#ifndef WL_SUBCOMPOSITOR_ERROR_ENUM
++#define WL_SUBCOMPOSITOR_ERROR_ENUM
++enum wl_subcompositor_error {
++ /**
++ * the to-be sub-surface is invalid
++ */
++ WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE = 0,
++};
++#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM */
++
++#define WL_SUBCOMPOSITOR_DESTROY 0
++#define WL_SUBCOMPOSITOR_GET_SUBSURFACE 1
++
++
++/**
++ * @ingroup iface_wl_subcompositor
++ */
++#define WL_SUBCOMPOSITOR_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subcompositor
++ */
++#define WL_SUBCOMPOSITOR_GET_SUBSURFACE_SINCE_VERSION 1
++
++/** @ingroup iface_wl_subcompositor */
++static inline void
++wl_subcompositor_set_user_data(struct wl_subcompositor *wl_subcompositor, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_subcompositor, user_data);
++}
++
++/** @ingroup iface_wl_subcompositor */
++static inline void *
++wl_subcompositor_get_user_data(struct wl_subcompositor *wl_subcompositor)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_subcompositor);
++}
++
++static inline uint32_t
++wl_subcompositor_get_version(struct wl_subcompositor *wl_subcompositor)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_subcompositor);
++}
++
++/**
++ * @ingroup iface_wl_subcompositor
++ *
++ * Informs the server that the client will not be using this
++ * protocol object anymore. This does not affect any other
++ * objects, wl_subsurface objects included.
++ */
++static inline void
++wl_subcompositor_destroy(struct wl_subcompositor *wl_subcompositor)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_subcompositor,
++ WL_SUBCOMPOSITOR_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subcompositor), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_subcompositor
++ *
++ * Create a sub-surface interface for the given surface, and
++ * associate it with the given parent surface. This turns a
++ * plain wl_surface into a sub-surface.
++ *
++ * The to-be sub-surface must not already have another role, and it
++ * must not have an existing wl_subsurface object. Otherwise a protocol
++ * error is raised.
++ */
++static inline struct wl_subsurface *
++wl_subcompositor_get_subsurface(struct wl_subcompositor *wl_subcompositor, struct wl_surface *surface, struct wl_surface *parent)
++{
++ struct wl_proxy *id;
++
++ id = wl_proxy_marshal_flags((struct wl_proxy *) wl_subcompositor,
++ WL_SUBCOMPOSITOR_GET_SUBSURFACE, &wl_subsurface_interface, wl_proxy_get_version((struct wl_proxy *) wl_subcompositor), 0, NULL, surface, parent);
++
++ return (struct wl_subsurface *) id;
++}
++
++#ifndef WL_SUBSURFACE_ERROR_ENUM
++#define WL_SUBSURFACE_ERROR_ENUM
++enum wl_subsurface_error {
++ /**
++ * wl_surface is not a sibling or the parent
++ */
++ WL_SUBSURFACE_ERROR_BAD_SURFACE = 0,
++};
++#endif /* WL_SUBSURFACE_ERROR_ENUM */
++
++#define WL_SUBSURFACE_DESTROY 0
++#define WL_SUBSURFACE_SET_POSITION 1
++#define WL_SUBSURFACE_PLACE_ABOVE 2
++#define WL_SUBSURFACE_PLACE_BELOW 3
++#define WL_SUBSURFACE_SET_SYNC 4
++#define WL_SUBSURFACE_SET_DESYNC 5
++
++
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_SET_POSITION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_PLACE_ABOVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_PLACE_BELOW_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_SET_SYNC_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_SET_DESYNC_SINCE_VERSION 1
++
++/** @ingroup iface_wl_subsurface */
++static inline void
++wl_subsurface_set_user_data(struct wl_subsurface *wl_subsurface, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) wl_subsurface, user_data);
++}
++
++/** @ingroup iface_wl_subsurface */
++static inline void *
++wl_subsurface_get_user_data(struct wl_subsurface *wl_subsurface)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) wl_subsurface);
++}
++
++static inline uint32_t
++wl_subsurface_get_version(struct wl_subsurface *wl_subsurface)
++{
++ return wl_proxy_get_version((struct wl_proxy *) wl_subsurface);
++}
++
++/**
++ * @ingroup iface_wl_subsurface
++ *
++ * The sub-surface interface is removed from the wl_surface object
++ * that was turned into a sub-surface with a
++ * wl_subcompositor.get_subsurface request. The wl_surface's association
++ * to the parent is deleted, and the wl_surface loses its role as
++ * a sub-surface. The wl_surface is unmapped.
++ */
++static inline void
++wl_subsurface_destroy(struct wl_subsurface *wl_subsurface)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface,
++ WL_SUBSURFACE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_subsurface
++ *
++ * This schedules a sub-surface position change.
++ * The sub-surface will be moved so that its origin (top left
++ * corner pixel) will be at the location x, y of the parent surface
++ * coordinate system. The coordinates are not restricted to the parent
++ * surface area. Negative values are allowed.
++ *
++ * The scheduled coordinates will take effect whenever the state of the
++ * parent surface is applied. When this happens depends on whether the
++ * parent surface is in synchronized mode or not. See
++ * wl_subsurface.set_sync and wl_subsurface.set_desync for details.
++ *
++ * If more than one set_position request is invoked by the client before
++ * the commit of the parent surface, the position of a new request always
++ * replaces the scheduled position from any previous request.
++ *
++ * The initial position is 0, 0.
++ */
++static inline void
++wl_subsurface_set_position(struct wl_subsurface *wl_subsurface, int32_t x, int32_t y)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface,
++ WL_SUBSURFACE_SET_POSITION, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0, x, y);
++}
++
++/**
++ * @ingroup iface_wl_subsurface
++ *
++ * This sub-surface is taken from the stack, and put back just
++ * above the reference surface, changing the z-order of the sub-surfaces.
++ * The reference surface must be one of the sibling surfaces, or the
++ * parent surface. Using any other surface, including this sub-surface,
++ * will cause a protocol error.
++ *
++ * The z-order is double-buffered. Requests are handled in order and
++ * applied immediately to a pending state. The final pending state is
++ * copied to the active state the next time the state of the parent
++ * surface is applied. When this happens depends on whether the parent
++ * surface is in synchronized mode or not. See wl_subsurface.set_sync and
++ * wl_subsurface.set_desync for details.
++ *
++ * A new sub-surface is initially added as the top-most in the stack
++ * of its siblings and parent.
++ */
++static inline void
++wl_subsurface_place_above(struct wl_subsurface *wl_subsurface, struct wl_surface *sibling)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface,
++ WL_SUBSURFACE_PLACE_ABOVE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0, sibling);
++}
++
++/**
++ * @ingroup iface_wl_subsurface
++ *
++ * The sub-surface is placed just below the reference surface.
++ * See wl_subsurface.place_above.
++ */
++static inline void
++wl_subsurface_place_below(struct wl_subsurface *wl_subsurface, struct wl_surface *sibling)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface,
++ WL_SUBSURFACE_PLACE_BELOW, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0, sibling);
++}
++
++/**
++ * @ingroup iface_wl_subsurface
++ *
++ * Change the commit behaviour of the sub-surface to synchronized
++ * mode, also described as the parent dependent mode.
++ *
++ * In synchronized mode, wl_surface.commit on a sub-surface will
++ * accumulate the committed state in a cache, but the state will
++ * not be applied and hence will not change the compositor output.
++ * The cached state is applied to the sub-surface immediately after
++ * the parent surface's state is applied. This ensures atomic
++ * updates of the parent and all its synchronized sub-surfaces.
++ * Applying the cached state will invalidate the cache, so further
++ * parent surface commits do not (re-)apply old state.
++ *
++ * See wl_subsurface for the recursive effect of this mode.
++ */
++static inline void
++wl_subsurface_set_sync(struct wl_subsurface *wl_subsurface)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface,
++ WL_SUBSURFACE_SET_SYNC, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0);
++}
++
++/**
++ * @ingroup iface_wl_subsurface
++ *
++ * Change the commit behaviour of the sub-surface to desynchronized
++ * mode, also described as independent or freely running mode.
++ *
++ * In desynchronized mode, wl_surface.commit on a sub-surface will
++ * apply the pending state directly, without caching, as happens
++ * normally with a wl_surface. Calling wl_surface.commit on the
++ * parent surface has no effect on the sub-surface's wl_surface
++ * state. This mode allows a sub-surface to be updated on its own.
++ *
++ * If cached state exists when wl_surface.commit is called in
++ * desynchronized mode, the pending state is added to the cached
++ * state, and applied as a whole. This invalidates the cache.
++ *
++ * Note: even if a sub-surface is set to desynchronized, a parent
++ * sub-surface may override it to behave as synchronized. For details,
++ * see wl_subsurface.
++ *
++ * If a surface's parent surface behaves as desynchronized, then
++ * the cached state is applied on set_desync.
++ */
++static inline void
++wl_subsurface_set_desync(struct wl_subsurface *wl_subsurface)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface,
++ WL_SUBSURFACE_SET_DESYNC, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0);
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
--- /dev/null
--- /dev/null
++/* SCANNER TEST */
++
++/*
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2010-2011 Intel Corporation
++ * Copyright © 2012-2013 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <stdint.h>
++#include "wayland-util.h"
++
++extern const struct wl_interface wl_buffer_interface;
++extern const struct wl_interface wl_callback_interface;
++extern const struct wl_interface wl_data_device_interface;
++extern const struct wl_interface wl_data_offer_interface;
++extern const struct wl_interface wl_data_source_interface;
++extern const struct wl_interface wl_keyboard_interface;
++extern const struct wl_interface wl_output_interface;
++extern const struct wl_interface wl_pointer_interface;
++extern const struct wl_interface wl_region_interface;
++extern const struct wl_interface wl_registry_interface;
++extern const struct wl_interface wl_seat_interface;
++extern const struct wl_interface wl_shell_surface_interface;
++extern const struct wl_interface wl_shm_pool_interface;
++extern const struct wl_interface wl_subsurface_interface;
++extern const struct wl_interface wl_surface_interface;
++extern const struct wl_interface wl_touch_interface;
++
++static const struct wl_interface *wayland_types[] = {
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ &wl_callback_interface,
++ &wl_registry_interface,
++ &wl_surface_interface,
++ &wl_region_interface,
++ &wl_buffer_interface,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ &wl_shm_pool_interface,
++ NULL,
++ NULL,
++ &wl_data_source_interface,
++ &wl_surface_interface,
++ &wl_surface_interface,
++ NULL,
++ &wl_data_source_interface,
++ NULL,
++ &wl_data_offer_interface,
++ NULL,
++ &wl_surface_interface,
++ NULL,
++ NULL,
++ &wl_data_offer_interface,
++ &wl_data_offer_interface,
++ &wl_data_source_interface,
++ &wl_data_device_interface,
++ &wl_seat_interface,
++ &wl_shell_surface_interface,
++ &wl_surface_interface,
++ &wl_seat_interface,
++ NULL,
++ &wl_seat_interface,
++ NULL,
++ NULL,
++ &wl_surface_interface,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ &wl_output_interface,
++ &wl_seat_interface,
++ NULL,
++ &wl_surface_interface,
++ NULL,
++ NULL,
++ NULL,
++ &wl_output_interface,
++ &wl_buffer_interface,
++ NULL,
++ NULL,
++ &wl_callback_interface,
++ &wl_region_interface,
++ &wl_region_interface,
++ &wl_output_interface,
++ &wl_output_interface,
++ &wl_pointer_interface,
++ &wl_keyboard_interface,
++ &wl_touch_interface,
++ NULL,
++ &wl_surface_interface,
++ NULL,
++ NULL,
++ NULL,
++ &wl_surface_interface,
++ NULL,
++ NULL,
++ NULL,
++ &wl_surface_interface,
++ NULL,
++ &wl_surface_interface,
++ NULL,
++ NULL,
++ &wl_surface_interface,
++ NULL,
++ NULL,
++ &wl_surface_interface,
++ NULL,
++ NULL,
++ NULL,
++ &wl_subsurface_interface,
++ &wl_surface_interface,
++ &wl_surface_interface,
++ &wl_surface_interface,
++ &wl_surface_interface,
++};
++
++static const struct wl_message wl_display_requests[] = {
++ { "sync", "n", wayland_types + 8 },
++ { "get_registry", "n", wayland_types + 9 },
++};
++
++static const struct wl_message wl_display_events[] = {
++ { "error", "ous", wayland_types + 0 },
++ { "delete_id", "u", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_display_interface = {
++ "wl_display", 1,
++ 2, wl_display_requests,
++ 2, wl_display_events,
++};
++
++static const struct wl_message wl_registry_requests[] = {
++ { "bind", "usun", wayland_types + 0 },
++};
++
++static const struct wl_message wl_registry_events[] = {
++ { "global", "usu", wayland_types + 0 },
++ { "global_remove", "u", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_registry_interface = {
++ "wl_registry", 1,
++ 1, wl_registry_requests,
++ 2, wl_registry_events,
++};
++
++static const struct wl_message wl_callback_events[] = {
++ { "done", "u", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_callback_interface = {
++ "wl_callback", 1,
++ 0, NULL,
++ 1, wl_callback_events,
++};
++
++static const struct wl_message wl_compositor_requests[] = {
++ { "create_surface", "n", wayland_types + 10 },
++ { "create_region", "n", wayland_types + 11 },
++};
++
++WL_EXPORT const struct wl_interface wl_compositor_interface = {
++ "wl_compositor", 4,
++ 2, wl_compositor_requests,
++ 0, NULL,
++};
++
++static const struct wl_message wl_shm_pool_requests[] = {
++ { "create_buffer", "niiiiu", wayland_types + 12 },
++ { "destroy", "", wayland_types + 0 },
++ { "resize", "i", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_shm_pool_interface = {
++ "wl_shm_pool", 1,
++ 3, wl_shm_pool_requests,
++ 0, NULL,
++};
++
++static const struct wl_message wl_shm_requests[] = {
++ { "create_pool", "nhi", wayland_types + 18 },
++};
++
++static const struct wl_message wl_shm_events[] = {
++ { "format", "u", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_shm_interface = {
++ "wl_shm", 1,
++ 1, wl_shm_requests,
++ 1, wl_shm_events,
++};
++
++static const struct wl_message wl_buffer_requests[] = {
++ { "destroy", "", wayland_types + 0 },
++};
++
++static const struct wl_message wl_buffer_events[] = {
++ { "release", "", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_buffer_interface = {
++ "wl_buffer", 1,
++ 1, wl_buffer_requests,
++ 1, wl_buffer_events,
++};
++
++static const struct wl_message wl_data_offer_requests[] = {
++ { "accept", "u?s", wayland_types + 0 },
++ { "receive", "sh", wayland_types + 0 },
++ { "destroy", "", wayland_types + 0 },
++ { "finish", "3", wayland_types + 0 },
++ { "set_actions", "3uu", wayland_types + 0 },
++};
++
++static const struct wl_message wl_data_offer_events[] = {
++ { "offer", "s", wayland_types + 0 },
++ { "source_actions", "3u", wayland_types + 0 },
++ { "action", "3u", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_data_offer_interface = {
++ "wl_data_offer", 3,
++ 5, wl_data_offer_requests,
++ 3, wl_data_offer_events,
++};
++
++static const struct wl_message wl_data_source_requests[] = {
++ { "offer", "s", wayland_types + 0 },
++ { "destroy", "", wayland_types + 0 },
++ { "set_actions", "3u", wayland_types + 0 },
++};
++
++static const struct wl_message wl_data_source_events[] = {
++ { "target", "?s", wayland_types + 0 },
++ { "send", "sh", wayland_types + 0 },
++ { "cancelled", "", wayland_types + 0 },
++ { "dnd_drop_performed", "3", wayland_types + 0 },
++ { "dnd_finished", "3", wayland_types + 0 },
++ { "action", "3u", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_data_source_interface = {
++ "wl_data_source", 3,
++ 3, wl_data_source_requests,
++ 6, wl_data_source_events,
++};
++
++static const struct wl_message wl_data_device_requests[] = {
++ { "start_drag", "?oo?ou", wayland_types + 21 },
++ { "set_selection", "?ou", wayland_types + 25 },
++ { "release", "2", wayland_types + 0 },
++};
++
++static const struct wl_message wl_data_device_events[] = {
++ { "data_offer", "n", wayland_types + 27 },
++ { "enter", "uoff?o", wayland_types + 28 },
++ { "leave", "", wayland_types + 0 },
++ { "motion", "uff", wayland_types + 0 },
++ { "drop", "", wayland_types + 0 },
++ { "selection", "?o", wayland_types + 33 },
++};
++
++WL_EXPORT const struct wl_interface wl_data_device_interface = {
++ "wl_data_device", 3,
++ 3, wl_data_device_requests,
++ 6, wl_data_device_events,
++};
++
++static const struct wl_message wl_data_device_manager_requests[] = {
++ { "create_data_source", "n", wayland_types + 34 },
++ { "get_data_device", "no", wayland_types + 35 },
++};
++
++WL_EXPORT const struct wl_interface wl_data_device_manager_interface = {
++ "wl_data_device_manager", 3,
++ 2, wl_data_device_manager_requests,
++ 0, NULL,
++};
++
++static const struct wl_message wl_shell_requests[] = {
++ { "get_shell_surface", "no", wayland_types + 37 },
++};
++
++WL_EXPORT const struct wl_interface wl_shell_interface = {
++ "wl_shell", 1,
++ 1, wl_shell_requests,
++ 0, NULL,
++};
++
++static const struct wl_message wl_shell_surface_requests[] = {
++ { "pong", "u", wayland_types + 0 },
++ { "move", "ou", wayland_types + 39 },
++ { "resize", "ouu", wayland_types + 41 },
++ { "set_toplevel", "", wayland_types + 0 },
++ { "set_transient", "oiiu", wayland_types + 44 },
++ { "set_fullscreen", "uu?o", wayland_types + 48 },
++ { "set_popup", "ouoiiu", wayland_types + 51 },
++ { "set_maximized", "?o", wayland_types + 57 },
++ { "set_title", "s", wayland_types + 0 },
++ { "set_class", "s", wayland_types + 0 },
++};
++
++static const struct wl_message wl_shell_surface_events[] = {
++ { "ping", "u", wayland_types + 0 },
++ { "configure", "uii", wayland_types + 0 },
++ { "popup_done", "", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_shell_surface_interface = {
++ "wl_shell_surface", 1,
++ 10, wl_shell_surface_requests,
++ 3, wl_shell_surface_events,
++};
++
++static const struct wl_message wl_surface_requests[] = {
++ { "destroy", "", wayland_types + 0 },
++ { "attach", "?oii", wayland_types + 58 },
++ { "damage", "iiii", wayland_types + 0 },
++ { "frame", "n", wayland_types + 61 },
++ { "set_opaque_region", "?o", wayland_types + 62 },
++ { "set_input_region", "?o", wayland_types + 63 },
++ { "commit", "", wayland_types + 0 },
++ { "set_buffer_transform", "2i", wayland_types + 0 },
++ { "set_buffer_scale", "3i", wayland_types + 0 },
++ { "damage_buffer", "4iiii", wayland_types + 0 },
++};
++
++static const struct wl_message wl_surface_events[] = {
++ { "enter", "o", wayland_types + 64 },
++ { "leave", "o", wayland_types + 65 },
++};
++
++WL_EXPORT const struct wl_interface wl_surface_interface = {
++ "wl_surface", 4,
++ 10, wl_surface_requests,
++ 2, wl_surface_events,
++};
++
++static const struct wl_message wl_seat_requests[] = {
++ { "get_pointer", "n", wayland_types + 66 },
++ { "get_keyboard", "n", wayland_types + 67 },
++ { "get_touch", "n", wayland_types + 68 },
++ { "release", "5", wayland_types + 0 },
++};
++
++static const struct wl_message wl_seat_events[] = {
++ { "capabilities", "u", wayland_types + 0 },
++ { "name", "2s", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_seat_interface = {
++ "wl_seat", 6,
++ 4, wl_seat_requests,
++ 2, wl_seat_events,
++};
++
++static const struct wl_message wl_pointer_requests[] = {
++ { "set_cursor", "u?oii", wayland_types + 69 },
++ { "release", "3", wayland_types + 0 },
++};
++
++static const struct wl_message wl_pointer_events[] = {
++ { "enter", "uoff", wayland_types + 73 },
++ { "leave", "uo", wayland_types + 77 },
++ { "motion", "uff", wayland_types + 0 },
++ { "button", "uuuu", wayland_types + 0 },
++ { "axis", "uuf", wayland_types + 0 },
++ { "frame", "5", wayland_types + 0 },
++ { "axis_source", "5u", wayland_types + 0 },
++ { "axis_stop", "5uu", wayland_types + 0 },
++ { "axis_discrete", "5ui", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_pointer_interface = {
++ "wl_pointer", 6,
++ 2, wl_pointer_requests,
++ 9, wl_pointer_events,
++};
++
++static const struct wl_message wl_keyboard_requests[] = {
++ { "release", "3", wayland_types + 0 },
++};
++
++static const struct wl_message wl_keyboard_events[] = {
++ { "keymap", "uhu", wayland_types + 0 },
++ { "enter", "uoa", wayland_types + 79 },
++ { "leave", "uo", wayland_types + 82 },
++ { "key", "uuuu", wayland_types + 0 },
++ { "modifiers", "uuuuu", wayland_types + 0 },
++ { "repeat_info", "4ii", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_keyboard_interface = {
++ "wl_keyboard", 6,
++ 1, wl_keyboard_requests,
++ 6, wl_keyboard_events,
++};
++
++static const struct wl_message wl_touch_requests[] = {
++ { "release", "3", wayland_types + 0 },
++};
++
++static const struct wl_message wl_touch_events[] = {
++ { "down", "uuoiff", wayland_types + 84 },
++ { "up", "uui", wayland_types + 0 },
++ { "motion", "uiff", wayland_types + 0 },
++ { "frame", "", wayland_types + 0 },
++ { "cancel", "", wayland_types + 0 },
++ { "shape", "6iff", wayland_types + 0 },
++ { "orientation", "6if", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_touch_interface = {
++ "wl_touch", 6,
++ 1, wl_touch_requests,
++ 7, wl_touch_events,
++};
++
++static const struct wl_message wl_output_requests[] = {
++ { "release", "3", wayland_types + 0 },
++};
++
++static const struct wl_message wl_output_events[] = {
++ { "geometry", "iiiiissi", wayland_types + 0 },
++ { "mode", "uiii", wayland_types + 0 },
++ { "done", "2", wayland_types + 0 },
++ { "scale", "2i", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_output_interface = {
++ "wl_output", 3,
++ 1, wl_output_requests,
++ 4, wl_output_events,
++};
++
++static const struct wl_message wl_region_requests[] = {
++ { "destroy", "", wayland_types + 0 },
++ { "add", "iiii", wayland_types + 0 },
++ { "subtract", "iiii", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_region_interface = {
++ "wl_region", 1,
++ 3, wl_region_requests,
++ 0, NULL,
++};
++
++static const struct wl_message wl_subcompositor_requests[] = {
++ { "destroy", "", wayland_types + 0 },
++ { "get_subsurface", "noo", wayland_types + 90 },
++};
++
++WL_EXPORT const struct wl_interface wl_subcompositor_interface = {
++ "wl_subcompositor", 1,
++ 2, wl_subcompositor_requests,
++ 0, NULL,
++};
++
++static const struct wl_message wl_subsurface_requests[] = {
++ { "destroy", "", wayland_types + 0 },
++ { "set_position", "ii", wayland_types + 0 },
++ { "place_above", "o", wayland_types + 93 },
++ { "place_below", "o", wayland_types + 94 },
++ { "set_sync", "", wayland_types + 0 },
++ { "set_desync", "", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_subsurface_interface = {
++ "wl_subsurface", 1,
++ 6, wl_subsurface_requests,
++ 0, NULL,
++};
++
--- /dev/null
--- /dev/null
++/* SCANNER TEST */
++
++#ifndef WAYLAND_SERVER_PROTOCOL_H
++#define WAYLAND_SERVER_PROTOCOL_H
++
++#include <stdint.h>
++#include <stddef.h>
++#include "wayland-server.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct wl_client;
++struct wl_resource;
++
++/**
++ * @page page_wayland The wayland protocol
++ * @section page_ifaces_wayland Interfaces
++ * - @subpage page_iface_wl_display - core global object
++ * - @subpage page_iface_wl_registry - global registry object
++ * - @subpage page_iface_wl_callback - callback object
++ * - @subpage page_iface_wl_compositor - the compositor singleton
++ * - @subpage page_iface_wl_shm_pool - a shared memory pool
++ * - @subpage page_iface_wl_shm - shared memory support
++ * - @subpage page_iface_wl_buffer - content for a wl_surface
++ * - @subpage page_iface_wl_data_offer - offer to transfer data
++ * - @subpage page_iface_wl_data_source - offer to transfer data
++ * - @subpage page_iface_wl_data_device - data transfer device
++ * - @subpage page_iface_wl_data_device_manager - data transfer interface
++ * - @subpage page_iface_wl_shell - create desktop-style surfaces
++ * - @subpage page_iface_wl_shell_surface - desktop-style metadata interface
++ * - @subpage page_iface_wl_surface - an onscreen surface
++ * - @subpage page_iface_wl_seat - group of input devices
++ * - @subpage page_iface_wl_pointer - pointer input device
++ * - @subpage page_iface_wl_keyboard - keyboard input device
++ * - @subpage page_iface_wl_touch - touchscreen input device
++ * - @subpage page_iface_wl_output - compositor output region
++ * - @subpage page_iface_wl_region - region interface
++ * - @subpage page_iface_wl_subcompositor - sub-surface compositing
++ * - @subpage page_iface_wl_subsurface - sub-surface interface to a wl_surface
++ * @section page_copyright_wayland Copyright
++ * <pre>
++ *
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2010-2011 Intel Corporation
++ * Copyright © 2012-2013 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ * </pre>
++ */
++struct wl_buffer;
++struct wl_callback;
++struct wl_compositor;
++struct wl_data_device;
++struct wl_data_device_manager;
++struct wl_data_offer;
++struct wl_data_source;
++struct wl_display;
++struct wl_keyboard;
++struct wl_output;
++struct wl_pointer;
++struct wl_region;
++struct wl_registry;
++struct wl_seat;
++struct wl_shell;
++struct wl_shell_surface;
++struct wl_shm;
++struct wl_shm_pool;
++struct wl_subcompositor;
++struct wl_subsurface;
++struct wl_surface;
++struct wl_touch;
++
++#ifndef WL_DISPLAY_INTERFACE
++#define WL_DISPLAY_INTERFACE
++/**
++ * @page page_iface_wl_display wl_display
++ * @section page_iface_wl_display_desc Description
++ *
++ * The core global object. This is a special singleton object. It
++ * is used for internal Wayland protocol features.
++ * @section page_iface_wl_display_api API
++ * See @ref iface_wl_display.
++ */
++/**
++ * @defgroup iface_wl_display The wl_display interface
++ *
++ * The core global object. This is a special singleton object. It
++ * is used for internal Wayland protocol features.
++ */
++extern const struct wl_interface wl_display_interface;
++#endif
++#ifndef WL_REGISTRY_INTERFACE
++#define WL_REGISTRY_INTERFACE
++/**
++ * @page page_iface_wl_registry wl_registry
++ * @section page_iface_wl_registry_desc Description
++ *
++ * The singleton global registry object. The server has a number of
++ * global objects that are available to all clients. These objects
++ * typically represent an actual object in the server (for example,
++ * an input device) or they are singleton objects that provide
++ * extension functionality.
++ *
++ * When a client creates a registry object, the registry object
++ * will emit a global event for each global currently in the
++ * registry. Globals come and go as a result of device or
++ * monitor hotplugs, reconfiguration or other events, and the
++ * registry will send out global and global_remove events to
++ * keep the client up to date with the changes. To mark the end
++ * of the initial burst of events, the client can use the
++ * wl_display.sync request immediately after calling
++ * wl_display.get_registry.
++ *
++ * A client can bind to a global object by using the bind
++ * request. This creates a client-side handle that lets the object
++ * emit events to the client and lets the client invoke requests on
++ * the object.
++ * @section page_iface_wl_registry_api API
++ * See @ref iface_wl_registry.
++ */
++/**
++ * @defgroup iface_wl_registry The wl_registry interface
++ *
++ * The singleton global registry object. The server has a number of
++ * global objects that are available to all clients. These objects
++ * typically represent an actual object in the server (for example,
++ * an input device) or they are singleton objects that provide
++ * extension functionality.
++ *
++ * When a client creates a registry object, the registry object
++ * will emit a global event for each global currently in the
++ * registry. Globals come and go as a result of device or
++ * monitor hotplugs, reconfiguration or other events, and the
++ * registry will send out global and global_remove events to
++ * keep the client up to date with the changes. To mark the end
++ * of the initial burst of events, the client can use the
++ * wl_display.sync request immediately after calling
++ * wl_display.get_registry.
++ *
++ * A client can bind to a global object by using the bind
++ * request. This creates a client-side handle that lets the object
++ * emit events to the client and lets the client invoke requests on
++ * the object.
++ */
++extern const struct wl_interface wl_registry_interface;
++#endif
++#ifndef WL_CALLBACK_INTERFACE
++#define WL_CALLBACK_INTERFACE
++/**
++ * @page page_iface_wl_callback wl_callback
++ * @section page_iface_wl_callback_desc Description
++ *
++ * Clients can handle the 'done' event to get notified when
++ * the related request is done.
++ * @section page_iface_wl_callback_api API
++ * See @ref iface_wl_callback.
++ */
++/**
++ * @defgroup iface_wl_callback The wl_callback interface
++ *
++ * Clients can handle the 'done' event to get notified when
++ * the related request is done.
++ */
++extern const struct wl_interface wl_callback_interface;
++#endif
++#ifndef WL_COMPOSITOR_INTERFACE
++#define WL_COMPOSITOR_INTERFACE
++/**
++ * @page page_iface_wl_compositor wl_compositor
++ * @section page_iface_wl_compositor_desc Description
++ *
++ * A compositor. This object is a singleton global. The
++ * compositor is in charge of combining the contents of multiple
++ * surfaces into one displayable output.
++ * @section page_iface_wl_compositor_api API
++ * See @ref iface_wl_compositor.
++ */
++/**
++ * @defgroup iface_wl_compositor The wl_compositor interface
++ *
++ * A compositor. This object is a singleton global. The
++ * compositor is in charge of combining the contents of multiple
++ * surfaces into one displayable output.
++ */
++extern const struct wl_interface wl_compositor_interface;
++#endif
++#ifndef WL_SHM_POOL_INTERFACE
++#define WL_SHM_POOL_INTERFACE
++/**
++ * @page page_iface_wl_shm_pool wl_shm_pool
++ * @section page_iface_wl_shm_pool_desc Description
++ *
++ * The wl_shm_pool object encapsulates a piece of memory shared
++ * between the compositor and client. Through the wl_shm_pool
++ * object, the client can allocate shared memory wl_buffer objects.
++ * All objects created through the same pool share the same
++ * underlying mapped memory. Reusing the mapped memory avoids the
++ * setup/teardown overhead and is useful when interactively resizing
++ * a surface or for many small buffers.
++ * @section page_iface_wl_shm_pool_api API
++ * See @ref iface_wl_shm_pool.
++ */
++/**
++ * @defgroup iface_wl_shm_pool The wl_shm_pool interface
++ *
++ * The wl_shm_pool object encapsulates a piece of memory shared
++ * between the compositor and client. Through the wl_shm_pool
++ * object, the client can allocate shared memory wl_buffer objects.
++ * All objects created through the same pool share the same
++ * underlying mapped memory. Reusing the mapped memory avoids the
++ * setup/teardown overhead and is useful when interactively resizing
++ * a surface or for many small buffers.
++ */
++extern const struct wl_interface wl_shm_pool_interface;
++#endif
++#ifndef WL_SHM_INTERFACE
++#define WL_SHM_INTERFACE
++/**
++ * @page page_iface_wl_shm wl_shm
++ * @section page_iface_wl_shm_desc Description
++ *
++ * A singleton global object that provides support for shared
++ * memory.
++ *
++ * Clients can create wl_shm_pool objects using the create_pool
++ * request.
++ *
++ * At connection setup time, the wl_shm object emits one or more
++ * format events to inform clients about the valid pixel formats
++ * that can be used for buffers.
++ * @section page_iface_wl_shm_api API
++ * See @ref iface_wl_shm.
++ */
++/**
++ * @defgroup iface_wl_shm The wl_shm interface
++ *
++ * A singleton global object that provides support for shared
++ * memory.
++ *
++ * Clients can create wl_shm_pool objects using the create_pool
++ * request.
++ *
++ * At connection setup time, the wl_shm object emits one or more
++ * format events to inform clients about the valid pixel formats
++ * that can be used for buffers.
++ */
++extern const struct wl_interface wl_shm_interface;
++#endif
++#ifndef WL_BUFFER_INTERFACE
++#define WL_BUFFER_INTERFACE
++/**
++ * @page page_iface_wl_buffer wl_buffer
++ * @section page_iface_wl_buffer_desc Description
++ *
++ * A buffer provides the content for a wl_surface. Buffers are
++ * created through factory interfaces such as wl_drm, wl_shm or
++ * similar. It has a width and a height and can be attached to a
++ * wl_surface, but the mechanism by which a client provides and
++ * updates the contents is defined by the buffer factory interface.
++ * @section page_iface_wl_buffer_api API
++ * See @ref iface_wl_buffer.
++ */
++/**
++ * @defgroup iface_wl_buffer The wl_buffer interface
++ *
++ * A buffer provides the content for a wl_surface. Buffers are
++ * created through factory interfaces such as wl_drm, wl_shm or
++ * similar. It has a width and a height and can be attached to a
++ * wl_surface, but the mechanism by which a client provides and
++ * updates the contents is defined by the buffer factory interface.
++ */
++extern const struct wl_interface wl_buffer_interface;
++#endif
++#ifndef WL_DATA_OFFER_INTERFACE
++#define WL_DATA_OFFER_INTERFACE
++/**
++ * @page page_iface_wl_data_offer wl_data_offer
++ * @section page_iface_wl_data_offer_desc Description
++ *
++ * A wl_data_offer represents a piece of data offered for transfer
++ * by another client (the source client). It is used by the
++ * copy-and-paste and drag-and-drop mechanisms. The offer
++ * describes the different mime types that the data can be
++ * converted to and provides the mechanism for transferring the
++ * data directly from the source client.
++ * @section page_iface_wl_data_offer_api API
++ * See @ref iface_wl_data_offer.
++ */
++/**
++ * @defgroup iface_wl_data_offer The wl_data_offer interface
++ *
++ * A wl_data_offer represents a piece of data offered for transfer
++ * by another client (the source client). It is used by the
++ * copy-and-paste and drag-and-drop mechanisms. The offer
++ * describes the different mime types that the data can be
++ * converted to and provides the mechanism for transferring the
++ * data directly from the source client.
++ */
++extern const struct wl_interface wl_data_offer_interface;
++#endif
++#ifndef WL_DATA_SOURCE_INTERFACE
++#define WL_DATA_SOURCE_INTERFACE
++/**
++ * @page page_iface_wl_data_source wl_data_source
++ * @section page_iface_wl_data_source_desc Description
++ *
++ * The wl_data_source object is the source side of a wl_data_offer.
++ * It is created by the source client in a data transfer and
++ * provides a way to describe the offered data and a way to respond
++ * to requests to transfer the data.
++ * @section page_iface_wl_data_source_api API
++ * See @ref iface_wl_data_source.
++ */
++/**
++ * @defgroup iface_wl_data_source The wl_data_source interface
++ *
++ * The wl_data_source object is the source side of a wl_data_offer.
++ * It is created by the source client in a data transfer and
++ * provides a way to describe the offered data and a way to respond
++ * to requests to transfer the data.
++ */
++extern const struct wl_interface wl_data_source_interface;
++#endif
++#ifndef WL_DATA_DEVICE_INTERFACE
++#define WL_DATA_DEVICE_INTERFACE
++/**
++ * @page page_iface_wl_data_device wl_data_device
++ * @section page_iface_wl_data_device_desc Description
++ *
++ * There is one wl_data_device per seat which can be obtained
++ * from the global wl_data_device_manager singleton.
++ *
++ * A wl_data_device provides access to inter-client data transfer
++ * mechanisms such as copy-and-paste and drag-and-drop.
++ * @section page_iface_wl_data_device_api API
++ * See @ref iface_wl_data_device.
++ */
++/**
++ * @defgroup iface_wl_data_device The wl_data_device interface
++ *
++ * There is one wl_data_device per seat which can be obtained
++ * from the global wl_data_device_manager singleton.
++ *
++ * A wl_data_device provides access to inter-client data transfer
++ * mechanisms such as copy-and-paste and drag-and-drop.
++ */
++extern const struct wl_interface wl_data_device_interface;
++#endif
++#ifndef WL_DATA_DEVICE_MANAGER_INTERFACE
++#define WL_DATA_DEVICE_MANAGER_INTERFACE
++/**
++ * @page page_iface_wl_data_device_manager wl_data_device_manager
++ * @section page_iface_wl_data_device_manager_desc Description
++ *
++ * The wl_data_device_manager is a singleton global object that
++ * provides access to inter-client data transfer mechanisms such as
++ * copy-and-paste and drag-and-drop. These mechanisms are tied to
++ * a wl_seat and this interface lets a client get a wl_data_device
++ * corresponding to a wl_seat.
++ *
++ * Depending on the version bound, the objects created from the bound
++ * wl_data_device_manager object will have different requirements for
++ * functioning properly. See wl_data_source.set_actions,
++ * wl_data_offer.accept and wl_data_offer.finish for details.
++ * @section page_iface_wl_data_device_manager_api API
++ * See @ref iface_wl_data_device_manager.
++ */
++/**
++ * @defgroup iface_wl_data_device_manager The wl_data_device_manager interface
++ *
++ * The wl_data_device_manager is a singleton global object that
++ * provides access to inter-client data transfer mechanisms such as
++ * copy-and-paste and drag-and-drop. These mechanisms are tied to
++ * a wl_seat and this interface lets a client get a wl_data_device
++ * corresponding to a wl_seat.
++ *
++ * Depending on the version bound, the objects created from the bound
++ * wl_data_device_manager object will have different requirements for
++ * functioning properly. See wl_data_source.set_actions,
++ * wl_data_offer.accept and wl_data_offer.finish for details.
++ */
++extern const struct wl_interface wl_data_device_manager_interface;
++#endif
++#ifndef WL_SHELL_INTERFACE
++#define WL_SHELL_INTERFACE
++/**
++ * @page page_iface_wl_shell wl_shell
++ * @section page_iface_wl_shell_desc Description
++ *
++ * This interface is implemented by servers that provide
++ * desktop-style user interfaces.
++ *
++ * It allows clients to associate a wl_shell_surface with
++ * a basic surface.
++ * @section page_iface_wl_shell_api API
++ * See @ref iface_wl_shell.
++ */
++/**
++ * @defgroup iface_wl_shell The wl_shell interface
++ *
++ * This interface is implemented by servers that provide
++ * desktop-style user interfaces.
++ *
++ * It allows clients to associate a wl_shell_surface with
++ * a basic surface.
++ */
++extern const struct wl_interface wl_shell_interface;
++#endif
++#ifndef WL_SHELL_SURFACE_INTERFACE
++#define WL_SHELL_SURFACE_INTERFACE
++/**
++ * @page page_iface_wl_shell_surface wl_shell_surface
++ * @section page_iface_wl_shell_surface_desc Description
++ *
++ * An interface that may be implemented by a wl_surface, for
++ * implementations that provide a desktop-style user interface.
++ *
++ * It provides requests to treat surfaces like toplevel, fullscreen
++ * or popup windows, move, resize or maximize them, associate
++ * metadata like title and class, etc.
++ *
++ * On the server side the object is automatically destroyed when
++ * the related wl_surface is destroyed. On the client side,
++ * wl_shell_surface_destroy() must be called before destroying
++ * the wl_surface object.
++ * @section page_iface_wl_shell_surface_api API
++ * See @ref iface_wl_shell_surface.
++ */
++/**
++ * @defgroup iface_wl_shell_surface The wl_shell_surface interface
++ *
++ * An interface that may be implemented by a wl_surface, for
++ * implementations that provide a desktop-style user interface.
++ *
++ * It provides requests to treat surfaces like toplevel, fullscreen
++ * or popup windows, move, resize or maximize them, associate
++ * metadata like title and class, etc.
++ *
++ * On the server side the object is automatically destroyed when
++ * the related wl_surface is destroyed. On the client side,
++ * wl_shell_surface_destroy() must be called before destroying
++ * the wl_surface object.
++ */
++extern const struct wl_interface wl_shell_surface_interface;
++#endif
++#ifndef WL_SURFACE_INTERFACE
++#define WL_SURFACE_INTERFACE
++/**
++ * @page page_iface_wl_surface wl_surface
++ * @section page_iface_wl_surface_desc Description
++ *
++ * A surface is a rectangular area that is displayed on the screen.
++ * It has a location, size and pixel contents.
++ *
++ * The size of a surface (and relative positions on it) is described
++ * in surface-local coordinates, which may differ from the buffer
++ * coordinates of the pixel content, in case a buffer_transform
++ * or a buffer_scale is used.
++ *
++ * A surface without a "role" is fairly useless: a compositor does
++ * not know where, when or how to present it. The role is the
++ * purpose of a wl_surface. Examples of roles are a cursor for a
++ * pointer (as set by wl_pointer.set_cursor), a drag icon
++ * (wl_data_device.start_drag), a sub-surface
++ * (wl_subcompositor.get_subsurface), and a window as defined by a
++ * shell protocol (e.g. wl_shell.get_shell_surface).
++ *
++ * A surface can have only one role at a time. Initially a
++ * wl_surface does not have a role. Once a wl_surface is given a
++ * role, it is set permanently for the whole lifetime of the
++ * wl_surface object. Giving the current role again is allowed,
++ * unless explicitly forbidden by the relevant interface
++ * specification.
++ *
++ * Surface roles are given by requests in other interfaces such as
++ * wl_pointer.set_cursor. The request should explicitly mention
++ * that this request gives a role to a wl_surface. Often, this
++ * request also creates a new protocol object that represents the
++ * role and adds additional functionality to wl_surface. When a
++ * client wants to destroy a wl_surface, they must destroy this 'role
++ * object' before the wl_surface.
++ *
++ * Destroying the role object does not remove the role from the
++ * wl_surface, but it may stop the wl_surface from "playing the role".
++ * For instance, if a wl_subsurface object is destroyed, the wl_surface
++ * it was created for will be unmapped and forget its position and
++ * z-order. It is allowed to create a wl_subsurface for the same
++ * wl_surface again, but it is not allowed to use the wl_surface as
++ * a cursor (cursor is a different role than sub-surface, and role
++ * switching is not allowed).
++ * @section page_iface_wl_surface_api API
++ * See @ref iface_wl_surface.
++ */
++/**
++ * @defgroup iface_wl_surface The wl_surface interface
++ *
++ * A surface is a rectangular area that is displayed on the screen.
++ * It has a location, size and pixel contents.
++ *
++ * The size of a surface (and relative positions on it) is described
++ * in surface-local coordinates, which may differ from the buffer
++ * coordinates of the pixel content, in case a buffer_transform
++ * or a buffer_scale is used.
++ *
++ * A surface without a "role" is fairly useless: a compositor does
++ * not know where, when or how to present it. The role is the
++ * purpose of a wl_surface. Examples of roles are a cursor for a
++ * pointer (as set by wl_pointer.set_cursor), a drag icon
++ * (wl_data_device.start_drag), a sub-surface
++ * (wl_subcompositor.get_subsurface), and a window as defined by a
++ * shell protocol (e.g. wl_shell.get_shell_surface).
++ *
++ * A surface can have only one role at a time. Initially a
++ * wl_surface does not have a role. Once a wl_surface is given a
++ * role, it is set permanently for the whole lifetime of the
++ * wl_surface object. Giving the current role again is allowed,
++ * unless explicitly forbidden by the relevant interface
++ * specification.
++ *
++ * Surface roles are given by requests in other interfaces such as
++ * wl_pointer.set_cursor. The request should explicitly mention
++ * that this request gives a role to a wl_surface. Often, this
++ * request also creates a new protocol object that represents the
++ * role and adds additional functionality to wl_surface. When a
++ * client wants to destroy a wl_surface, they must destroy this 'role
++ * object' before the wl_surface.
++ *
++ * Destroying the role object does not remove the role from the
++ * wl_surface, but it may stop the wl_surface from "playing the role".
++ * For instance, if a wl_subsurface object is destroyed, the wl_surface
++ * it was created for will be unmapped and forget its position and
++ * z-order. It is allowed to create a wl_subsurface for the same
++ * wl_surface again, but it is not allowed to use the wl_surface as
++ * a cursor (cursor is a different role than sub-surface, and role
++ * switching is not allowed).
++ */
++extern const struct wl_interface wl_surface_interface;
++#endif
++#ifndef WL_SEAT_INTERFACE
++#define WL_SEAT_INTERFACE
++/**
++ * @page page_iface_wl_seat wl_seat
++ * @section page_iface_wl_seat_desc Description
++ *
++ * A seat is a group of keyboards, pointer and touch devices. This
++ * object is published as a global during start up, or when such a
++ * device is hot plugged. A seat typically has a pointer and
++ * maintains a keyboard focus and a pointer focus.
++ * @section page_iface_wl_seat_api API
++ * See @ref iface_wl_seat.
++ */
++/**
++ * @defgroup iface_wl_seat The wl_seat interface
++ *
++ * A seat is a group of keyboards, pointer and touch devices. This
++ * object is published as a global during start up, or when such a
++ * device is hot plugged. A seat typically has a pointer and
++ * maintains a keyboard focus and a pointer focus.
++ */
++extern const struct wl_interface wl_seat_interface;
++#endif
++#ifndef WL_POINTER_INTERFACE
++#define WL_POINTER_INTERFACE
++/**
++ * @page page_iface_wl_pointer wl_pointer
++ * @section page_iface_wl_pointer_desc Description
++ *
++ * The wl_pointer interface represents one or more input devices,
++ * such as mice, which control the pointer location and pointer_focus
++ * of a seat.
++ *
++ * The wl_pointer interface generates motion, enter and leave
++ * events for the surfaces that the pointer is located over,
++ * and button and axis events for button presses, button releases
++ * and scrolling.
++ * @section page_iface_wl_pointer_api API
++ * See @ref iface_wl_pointer.
++ */
++/**
++ * @defgroup iface_wl_pointer The wl_pointer interface
++ *
++ * The wl_pointer interface represents one or more input devices,
++ * such as mice, which control the pointer location and pointer_focus
++ * of a seat.
++ *
++ * The wl_pointer interface generates motion, enter and leave
++ * events for the surfaces that the pointer is located over,
++ * and button and axis events for button presses, button releases
++ * and scrolling.
++ */
++extern const struct wl_interface wl_pointer_interface;
++#endif
++#ifndef WL_KEYBOARD_INTERFACE
++#define WL_KEYBOARD_INTERFACE
++/**
++ * @page page_iface_wl_keyboard wl_keyboard
++ * @section page_iface_wl_keyboard_desc Description
++ *
++ * The wl_keyboard interface represents one or more keyboards
++ * associated with a seat.
++ * @section page_iface_wl_keyboard_api API
++ * See @ref iface_wl_keyboard.
++ */
++/**
++ * @defgroup iface_wl_keyboard The wl_keyboard interface
++ *
++ * The wl_keyboard interface represents one or more keyboards
++ * associated with a seat.
++ */
++extern const struct wl_interface wl_keyboard_interface;
++#endif
++#ifndef WL_TOUCH_INTERFACE
++#define WL_TOUCH_INTERFACE
++/**
++ * @page page_iface_wl_touch wl_touch
++ * @section page_iface_wl_touch_desc Description
++ *
++ * The wl_touch interface represents a touchscreen
++ * associated with a seat.
++ *
++ * Touch interactions can consist of one or more contacts.
++ * For each contact, a series of events is generated, starting
++ * with a down event, followed by zero or more motion events,
++ * and ending with an up event. Events relating to the same
++ * contact point can be identified by the ID of the sequence.
++ * @section page_iface_wl_touch_api API
++ * See @ref iface_wl_touch.
++ */
++/**
++ * @defgroup iface_wl_touch The wl_touch interface
++ *
++ * The wl_touch interface represents a touchscreen
++ * associated with a seat.
++ *
++ * Touch interactions can consist of one or more contacts.
++ * For each contact, a series of events is generated, starting
++ * with a down event, followed by zero or more motion events,
++ * and ending with an up event. Events relating to the same
++ * contact point can be identified by the ID of the sequence.
++ */
++extern const struct wl_interface wl_touch_interface;
++#endif
++#ifndef WL_OUTPUT_INTERFACE
++#define WL_OUTPUT_INTERFACE
++/**
++ * @page page_iface_wl_output wl_output
++ * @section page_iface_wl_output_desc Description
++ *
++ * An output describes part of the compositor geometry. The
++ * compositor works in the 'compositor coordinate system' and an
++ * output corresponds to a rectangular area in that space that is
++ * actually visible. This typically corresponds to a monitor that
++ * displays part of the compositor space. This object is published
++ * as global during start up, or when a monitor is hotplugged.
++ * @section page_iface_wl_output_api API
++ * See @ref iface_wl_output.
++ */
++/**
++ * @defgroup iface_wl_output The wl_output interface
++ *
++ * An output describes part of the compositor geometry. The
++ * compositor works in the 'compositor coordinate system' and an
++ * output corresponds to a rectangular area in that space that is
++ * actually visible. This typically corresponds to a monitor that
++ * displays part of the compositor space. This object is published
++ * as global during start up, or when a monitor is hotplugged.
++ */
++extern const struct wl_interface wl_output_interface;
++#endif
++#ifndef WL_REGION_INTERFACE
++#define WL_REGION_INTERFACE
++/**
++ * @page page_iface_wl_region wl_region
++ * @section page_iface_wl_region_desc Description
++ *
++ * A region object describes an area.
++ *
++ * Region objects are used to describe the opaque and input
++ * regions of a surface.
++ * @section page_iface_wl_region_api API
++ * See @ref iface_wl_region.
++ */
++/**
++ * @defgroup iface_wl_region The wl_region interface
++ *
++ * A region object describes an area.
++ *
++ * Region objects are used to describe the opaque and input
++ * regions of a surface.
++ */
++extern const struct wl_interface wl_region_interface;
++#endif
++#ifndef WL_SUBCOMPOSITOR_INTERFACE
++#define WL_SUBCOMPOSITOR_INTERFACE
++/**
++ * @page page_iface_wl_subcompositor wl_subcompositor
++ * @section page_iface_wl_subcompositor_desc Description
++ *
++ * The global interface exposing sub-surface compositing capabilities.
++ * A wl_surface, that has sub-surfaces associated, is called the
++ * parent surface. Sub-surfaces can be arbitrarily nested and create
++ * a tree of sub-surfaces.
++ *
++ * The root surface in a tree of sub-surfaces is the main
++ * surface. The main surface cannot be a sub-surface, because
++ * sub-surfaces must always have a parent.
++ *
++ * A main surface with its sub-surfaces forms a (compound) window.
++ * For window management purposes, this set of wl_surface objects is
++ * to be considered as a single window, and it should also behave as
++ * such.
++ *
++ * The aim of sub-surfaces is to offload some of the compositing work
++ * within a window from clients to the compositor. A prime example is
++ * a video player with decorations and video in separate wl_surface
++ * objects. This should allow the compositor to pass YUV video buffer
++ * processing to dedicated overlay hardware when possible.
++ * @section page_iface_wl_subcompositor_api API
++ * See @ref iface_wl_subcompositor.
++ */
++/**
++ * @defgroup iface_wl_subcompositor The wl_subcompositor interface
++ *
++ * The global interface exposing sub-surface compositing capabilities.
++ * A wl_surface, that has sub-surfaces associated, is called the
++ * parent surface. Sub-surfaces can be arbitrarily nested and create
++ * a tree of sub-surfaces.
++ *
++ * The root surface in a tree of sub-surfaces is the main
++ * surface. The main surface cannot be a sub-surface, because
++ * sub-surfaces must always have a parent.
++ *
++ * A main surface with its sub-surfaces forms a (compound) window.
++ * For window management purposes, this set of wl_surface objects is
++ * to be considered as a single window, and it should also behave as
++ * such.
++ *
++ * The aim of sub-surfaces is to offload some of the compositing work
++ * within a window from clients to the compositor. A prime example is
++ * a video player with decorations and video in separate wl_surface
++ * objects. This should allow the compositor to pass YUV video buffer
++ * processing to dedicated overlay hardware when possible.
++ */
++extern const struct wl_interface wl_subcompositor_interface;
++#endif
++#ifndef WL_SUBSURFACE_INTERFACE
++#define WL_SUBSURFACE_INTERFACE
++/**
++ * @page page_iface_wl_subsurface wl_subsurface
++ * @section page_iface_wl_subsurface_desc Description
++ *
++ * An additional interface to a wl_surface object, which has been
++ * made a sub-surface. A sub-surface has one parent surface. A
++ * sub-surface's size and position are not limited to that of the parent.
++ * Particularly, a sub-surface is not automatically clipped to its
++ * parent's area.
++ *
++ * A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
++ * and the parent surface is mapped. The order of which one happens
++ * first is irrelevant. A sub-surface is hidden if the parent becomes
++ * hidden, or if a NULL wl_buffer is applied. These rules apply
++ * recursively through the tree of surfaces.
++ *
++ * The behaviour of a wl_surface.commit request on a sub-surface
++ * depends on the sub-surface's mode. The possible modes are
++ * synchronized and desynchronized, see methods
++ * wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
++ * mode caches the wl_surface state to be applied when the parent's
++ * state gets applied, and desynchronized mode applies the pending
++ * wl_surface state directly. A sub-surface is initially in the
++ * synchronized mode.
++ *
++ * Sub-surfaces have also other kind of state, which is managed by
++ * wl_subsurface requests, as opposed to wl_surface requests. This
++ * state includes the sub-surface position relative to the parent
++ * surface (wl_subsurface.set_position), and the stacking order of
++ * the parent and its sub-surfaces (wl_subsurface.place_above and
++ * .place_below). This state is applied when the parent surface's
++ * wl_surface state is applied, regardless of the sub-surface's mode.
++ * As the exception, set_sync and set_desync are effective immediately.
++ *
++ * The main surface can be thought to be always in desynchronized mode,
++ * since it does not have a parent in the sub-surfaces sense.
++ *
++ * Even if a sub-surface is in desynchronized mode, it will behave as
++ * in synchronized mode, if its parent surface behaves as in
++ * synchronized mode. This rule is applied recursively throughout the
++ * tree of surfaces. This means, that one can set a sub-surface into
++ * synchronized mode, and then assume that all its child and grand-child
++ * sub-surfaces are synchronized, too, without explicitly setting them.
++ *
++ * If the wl_surface associated with the wl_subsurface is destroyed, the
++ * wl_subsurface object becomes inert. Note, that destroying either object
++ * takes effect immediately. If you need to synchronize the removal
++ * of a sub-surface to the parent surface update, unmap the sub-surface
++ * first by attaching a NULL wl_buffer, update parent, and then destroy
++ * the sub-surface.
++ *
++ * If the parent wl_surface object is destroyed, the sub-surface is
++ * unmapped.
++ * @section page_iface_wl_subsurface_api API
++ * See @ref iface_wl_subsurface.
++ */
++/**
++ * @defgroup iface_wl_subsurface The wl_subsurface interface
++ *
++ * An additional interface to a wl_surface object, which has been
++ * made a sub-surface. A sub-surface has one parent surface. A
++ * sub-surface's size and position are not limited to that of the parent.
++ * Particularly, a sub-surface is not automatically clipped to its
++ * parent's area.
++ *
++ * A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
++ * and the parent surface is mapped. The order of which one happens
++ * first is irrelevant. A sub-surface is hidden if the parent becomes
++ * hidden, or if a NULL wl_buffer is applied. These rules apply
++ * recursively through the tree of surfaces.
++ *
++ * The behaviour of a wl_surface.commit request on a sub-surface
++ * depends on the sub-surface's mode. The possible modes are
++ * synchronized and desynchronized, see methods
++ * wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
++ * mode caches the wl_surface state to be applied when the parent's
++ * state gets applied, and desynchronized mode applies the pending
++ * wl_surface state directly. A sub-surface is initially in the
++ * synchronized mode.
++ *
++ * Sub-surfaces have also other kind of state, which is managed by
++ * wl_subsurface requests, as opposed to wl_surface requests. This
++ * state includes the sub-surface position relative to the parent
++ * surface (wl_subsurface.set_position), and the stacking order of
++ * the parent and its sub-surfaces (wl_subsurface.place_above and
++ * .place_below). This state is applied when the parent surface's
++ * wl_surface state is applied, regardless of the sub-surface's mode.
++ * As the exception, set_sync and set_desync are effective immediately.
++ *
++ * The main surface can be thought to be always in desynchronized mode,
++ * since it does not have a parent in the sub-surfaces sense.
++ *
++ * Even if a sub-surface is in desynchronized mode, it will behave as
++ * in synchronized mode, if its parent surface behaves as in
++ * synchronized mode. This rule is applied recursively throughout the
++ * tree of surfaces. This means, that one can set a sub-surface into
++ * synchronized mode, and then assume that all its child and grand-child
++ * sub-surfaces are synchronized, too, without explicitly setting them.
++ *
++ * If the wl_surface associated with the wl_subsurface is destroyed, the
++ * wl_subsurface object becomes inert. Note, that destroying either object
++ * takes effect immediately. If you need to synchronize the removal
++ * of a sub-surface to the parent surface update, unmap the sub-surface
++ * first by attaching a NULL wl_buffer, update parent, and then destroy
++ * the sub-surface.
++ *
++ * If the parent wl_surface object is destroyed, the sub-surface is
++ * unmapped.
++ */
++extern const struct wl_interface wl_subsurface_interface;
++#endif
++
++#ifndef WL_DISPLAY_ERROR_ENUM
++#define WL_DISPLAY_ERROR_ENUM
++/**
++ * @ingroup iface_wl_display
++ * global error values
++ *
++ * These errors are global and can be emitted in response to any
++ * server request.
++ */
++enum wl_display_error {
++ /**
++ * server couldn't find object
++ */
++ WL_DISPLAY_ERROR_INVALID_OBJECT = 0,
++ /**
++ * method doesn't exist on the specified interface
++ */
++ WL_DISPLAY_ERROR_INVALID_METHOD = 1,
++ /**
++ * server is out of memory
++ */
++ WL_DISPLAY_ERROR_NO_MEMORY = 2,
++};
++#endif /* WL_DISPLAY_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_display
++ * @struct wl_display_interface
++ */
++struct wl_display_interface {
++ /**
++ * asynchronous roundtrip
++ *
++ * The sync request asks the server to emit the 'done' event on
++ * the returned wl_callback object. Since requests are handled
++ * in-order and events are delivered in-order, this can be used as
++ * a barrier to ensure all previous requests and the resulting
++ * events have been handled.
++ *
++ * The object returned by this request will be destroyed by the
++ * compositor after the callback is fired and as such the client
++ * must not attempt to use it after that point.
++ *
++ * The callback_data passed in the callback is the event serial.
++ * @param callback callback object for the sync request
++ */
++ void (*sync)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t callback);
++ /**
++ * get global registry object
++ *
++ * This request creates a registry object that allows the client
++ * to list and bind the global objects available from the
++ * compositor.
++ * @param registry global registry object
++ */
++ void (*get_registry)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t registry);
++};
++
++#define WL_DISPLAY_ERROR 0
++#define WL_DISPLAY_DELETE_ID 1
++
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_ERROR_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_DELETE_ID_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_SYNC_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_GET_REGISTRY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_registry
++ * @struct wl_registry_interface
++ */
++struct wl_registry_interface {
++ /**
++ * bind an object to the display
++ *
++ * Binds a new, client-created object to the server using the
++ * specified name as the identifier.
++ * @param name unique numeric name of the object
++ * @param interface name of the objects interface
++ * @param version version of the objects interface
++ * @param id bounded object
++ */
++ void (*bind)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t name,
++ const char *interface, uint32_t version, uint32_t id);
++};
++
++#define WL_REGISTRY_GLOBAL 0
++#define WL_REGISTRY_GLOBAL_REMOVE 1
++
++/**
++ * @ingroup iface_wl_registry
++ */
++#define WL_REGISTRY_GLOBAL_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_registry
++ */
++#define WL_REGISTRY_GLOBAL_REMOVE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_registry
++ */
++#define WL_REGISTRY_BIND_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_registry
++ * Sends an global event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param name numeric name of the global object
++ * @param interface interface implemented by the object
++ * @param version interface version
++ */
++static inline void
++wl_registry_send_global(struct wl_resource *resource_, uint32_t name, const char *interface, uint32_t version)
++{
++ wl_resource_post_event(resource_, WL_REGISTRY_GLOBAL, name, interface, version);
++}
++
++/**
++ * @ingroup iface_wl_registry
++ * Sends an global_remove event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param name numeric name of the global object
++ */
++static inline void
++wl_registry_send_global_remove(struct wl_resource *resource_, uint32_t name)
++{
++ wl_resource_post_event(resource_, WL_REGISTRY_GLOBAL_REMOVE, name);
++}
++
++#define WL_CALLBACK_DONE 0
++
++/**
++ * @ingroup iface_wl_callback
++ */
++#define WL_CALLBACK_DONE_SINCE_VERSION 1
++
++
++/**
++ * @ingroup iface_wl_callback
++ * Sends an done event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param callback_data request-specific data for the callback
++ */
++static inline void
++wl_callback_send_done(struct wl_resource *resource_, uint32_t callback_data)
++{
++ wl_resource_post_event(resource_, WL_CALLBACK_DONE, callback_data);
++}
++
++/**
++ * @ingroup iface_wl_compositor
++ * @struct wl_compositor_interface
++ */
++struct wl_compositor_interface {
++ /**
++ * create new surface
++ *
++ * Ask the compositor to create a new surface.
++ * @param id the new surface
++ */
++ void (*create_surface)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t id);
++ /**
++ * create new region
++ *
++ * Ask the compositor to create a new region.
++ * @param id the new region
++ */
++ void (*create_region)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t id);
++};
++
++
++/**
++ * @ingroup iface_wl_compositor
++ */
++#define WL_COMPOSITOR_CREATE_SURFACE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_compositor
++ */
++#define WL_COMPOSITOR_CREATE_REGION_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_shm_pool
++ * @struct wl_shm_pool_interface
++ */
++struct wl_shm_pool_interface {
++ /**
++ * create a buffer from the pool
++ *
++ * Create a wl_buffer object from the pool.
++ *
++ * The buffer is created offset bytes into the pool and has width
++ * and height as specified. The stride argument specifies the
++ * number of bytes from the beginning of one row to the beginning
++ * of the next. The format is the pixel format of the buffer and
++ * must be one of those advertised through the wl_shm.format event.
++ *
++ * A buffer will keep a reference to the pool it was created from
++ * so it is valid to destroy the pool immediately after creating a
++ * buffer from it.
++ * @param id buffer to create
++ * @param offset buffer byte offset within the pool
++ * @param width buffer width, in pixels
++ * @param height buffer height, in pixels
++ * @param stride number of bytes from the beginning of one row to the beginning of the next row
++ * @param format buffer pixel format
++ */
++ void (*create_buffer)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t id,
++ int32_t offset,
++ int32_t width,
++ int32_t height,
++ int32_t stride,
++ uint32_t format);
++ /**
++ * destroy the pool
++ *
++ * Destroy the shared memory pool.
++ *
++ * The mmapped memory will be released when all buffers that have
++ * been created from this pool are gone.
++ */
++ void (*destroy)(struct wl_client *client,
++ struct wl_resource *resource);
++ /**
++ * change the size of the pool mapping
++ *
++ * This request will cause the server to remap the backing memory
++ * for the pool from the file descriptor passed when the pool was
++ * created, but using the new size. This request can only be used
++ * to make the pool bigger.
++ * @param size new size of the pool, in bytes
++ */
++ void (*resize)(struct wl_client *client,
++ struct wl_resource *resource,
++ int32_t size);
++};
++
++
++/**
++ * @ingroup iface_wl_shm_pool
++ */
++#define WL_SHM_POOL_CREATE_BUFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shm_pool
++ */
++#define WL_SHM_POOL_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shm_pool
++ */
++#define WL_SHM_POOL_RESIZE_SINCE_VERSION 1
++
++#ifndef WL_SHM_ERROR_ENUM
++#define WL_SHM_ERROR_ENUM
++/**
++ * @ingroup iface_wl_shm
++ * wl_shm error values
++ *
++ * These errors can be emitted in response to wl_shm requests.
++ */
++enum wl_shm_error {
++ /**
++ * buffer format is not known
++ */
++ WL_SHM_ERROR_INVALID_FORMAT = 0,
++ /**
++ * invalid size or stride during pool or buffer creation
++ */
++ WL_SHM_ERROR_INVALID_STRIDE = 1,
++ /**
++ * mmapping the file descriptor failed
++ */
++ WL_SHM_ERROR_INVALID_FD = 2,
++};
++#endif /* WL_SHM_ERROR_ENUM */
++
++#ifndef WL_SHM_FORMAT_ENUM
++#define WL_SHM_FORMAT_ENUM
++/**
++ * @ingroup iface_wl_shm
++ * pixel formats
++ *
++ * This describes the memory layout of an individual pixel.
++ *
++ * All renderers should support argb8888 and xrgb8888 but any other
++ * formats are optional and may not be supported by the particular
++ * renderer in use.
++ *
++ * The drm format codes match the macros defined in drm_fourcc.h.
++ * The formats actually supported by the compositor will be
++ * reported by the format event.
++ */
++enum wl_shm_format {
++ /**
++ * 32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_ARGB8888 = 0,
++ /**
++ * 32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_XRGB8888 = 1,
++ /**
++ * 8-bit color index format, [7:0] C
++ */
++ WL_SHM_FORMAT_C8 = 0x20203843,
++ /**
++ * 8-bit RGB format, [7:0] R:G:B 3:3:2
++ */
++ WL_SHM_FORMAT_RGB332 = 0x38424752,
++ /**
++ * 8-bit BGR format, [7:0] B:G:R 2:3:3
++ */
++ WL_SHM_FORMAT_BGR233 = 0x38524742,
++ /**
++ * 16-bit xRGB format, [15:0] x:R:G:B 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_XRGB4444 = 0x32315258,
++ /**
++ * 16-bit xBGR format, [15:0] x:B:G:R 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_XBGR4444 = 0x32314258,
++ /**
++ * 16-bit RGBx format, [15:0] R:G:B:x 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_RGBX4444 = 0x32315852,
++ /**
++ * 16-bit BGRx format, [15:0] B:G:R:x 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_BGRX4444 = 0x32315842,
++ /**
++ * 16-bit ARGB format, [15:0] A:R:G:B 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_ARGB4444 = 0x32315241,
++ /**
++ * 16-bit ABGR format, [15:0] A:B:G:R 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_ABGR4444 = 0x32314241,
++ /**
++ * 16-bit RBGA format, [15:0] R:G:B:A 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_RGBA4444 = 0x32314152,
++ /**
++ * 16-bit BGRA format, [15:0] B:G:R:A 4:4:4:4 little endian
++ */
++ WL_SHM_FORMAT_BGRA4444 = 0x32314142,
++ /**
++ * 16-bit xRGB format, [15:0] x:R:G:B 1:5:5:5 little endian
++ */
++ WL_SHM_FORMAT_XRGB1555 = 0x35315258,
++ /**
++ * 16-bit xBGR 1555 format, [15:0] x:B:G:R 1:5:5:5 little endian
++ */
++ WL_SHM_FORMAT_XBGR1555 = 0x35314258,
++ /**
++ * 16-bit RGBx 5551 format, [15:0] R:G:B:x 5:5:5:1 little endian
++ */
++ WL_SHM_FORMAT_RGBX5551 = 0x35315852,
++ /**
++ * 16-bit BGRx 5551 format, [15:0] B:G:R:x 5:5:5:1 little endian
++ */
++ WL_SHM_FORMAT_BGRX5551 = 0x35315842,
++ /**
++ * 16-bit ARGB 1555 format, [15:0] A:R:G:B 1:5:5:5 little endian
++ */
++ WL_SHM_FORMAT_ARGB1555 = 0x35315241,
++ /**
++ * 16-bit ABGR 1555 format, [15:0] A:B:G:R 1:5:5:5 little endian
++ */
++ WL_SHM_FORMAT_ABGR1555 = 0x35314241,
++ /**
++ * 16-bit RGBA 5551 format, [15:0] R:G:B:A 5:5:5:1 little endian
++ */
++ WL_SHM_FORMAT_RGBA5551 = 0x35314152,
++ /**
++ * 16-bit BGRA 5551 format, [15:0] B:G:R:A 5:5:5:1 little endian
++ */
++ WL_SHM_FORMAT_BGRA5551 = 0x35314142,
++ /**
++ * 16-bit RGB 565 format, [15:0] R:G:B 5:6:5 little endian
++ */
++ WL_SHM_FORMAT_RGB565 = 0x36314752,
++ /**
++ * 16-bit BGR 565 format, [15:0] B:G:R 5:6:5 little endian
++ */
++ WL_SHM_FORMAT_BGR565 = 0x36314742,
++ /**
++ * 24-bit RGB format, [23:0] R:G:B little endian
++ */
++ WL_SHM_FORMAT_RGB888 = 0x34324752,
++ /**
++ * 24-bit BGR format, [23:0] B:G:R little endian
++ */
++ WL_SHM_FORMAT_BGR888 = 0x34324742,
++ /**
++ * 32-bit xBGR format, [31:0] x:B:G:R 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_XBGR8888 = 0x34324258,
++ /**
++ * 32-bit RGBx format, [31:0] R:G:B:x 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_RGBX8888 = 0x34325852,
++ /**
++ * 32-bit BGRx format, [31:0] B:G:R:x 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_BGRX8888 = 0x34325842,
++ /**
++ * 32-bit ABGR format, [31:0] A:B:G:R 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_ABGR8888 = 0x34324241,
++ /**
++ * 32-bit RGBA format, [31:0] R:G:B:A 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_RGBA8888 = 0x34324152,
++ /**
++ * 32-bit BGRA format, [31:0] B:G:R:A 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_BGRA8888 = 0x34324142,
++ /**
++ * 32-bit xRGB format, [31:0] x:R:G:B 2:10:10:10 little endian
++ */
++ WL_SHM_FORMAT_XRGB2101010 = 0x30335258,
++ /**
++ * 32-bit xBGR format, [31:0] x:B:G:R 2:10:10:10 little endian
++ */
++ WL_SHM_FORMAT_XBGR2101010 = 0x30334258,
++ /**
++ * 32-bit RGBx format, [31:0] R:G:B:x 10:10:10:2 little endian
++ */
++ WL_SHM_FORMAT_RGBX1010102 = 0x30335852,
++ /**
++ * 32-bit BGRx format, [31:0] B:G:R:x 10:10:10:2 little endian
++ */
++ WL_SHM_FORMAT_BGRX1010102 = 0x30335842,
++ /**
++ * 32-bit ARGB format, [31:0] A:R:G:B 2:10:10:10 little endian
++ */
++ WL_SHM_FORMAT_ARGB2101010 = 0x30335241,
++ /**
++ * 32-bit ABGR format, [31:0] A:B:G:R 2:10:10:10 little endian
++ */
++ WL_SHM_FORMAT_ABGR2101010 = 0x30334241,
++ /**
++ * 32-bit RGBA format, [31:0] R:G:B:A 10:10:10:2 little endian
++ */
++ WL_SHM_FORMAT_RGBA1010102 = 0x30334152,
++ /**
++ * 32-bit BGRA format, [31:0] B:G:R:A 10:10:10:2 little endian
++ */
++ WL_SHM_FORMAT_BGRA1010102 = 0x30334142,
++ /**
++ * packed YCbCr format, [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_YUYV = 0x56595559,
++ /**
++ * packed YCbCr format, [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_YVYU = 0x55595659,
++ /**
++ * packed YCbCr format, [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_UYVY = 0x59565955,
++ /**
++ * packed YCbCr format, [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_VYUY = 0x59555956,
++ /**
++ * packed AYCbCr format, [31:0] A:Y:Cb:Cr 8:8:8:8 little endian
++ */
++ WL_SHM_FORMAT_AYUV = 0x56555941,
++ /**
++ * 2 plane YCbCr Cr:Cb format, 2x2 subsampled Cr:Cb plane
++ */
++ WL_SHM_FORMAT_NV12 = 0x3231564e,
++ /**
++ * 2 plane YCbCr Cb:Cr format, 2x2 subsampled Cb:Cr plane
++ */
++ WL_SHM_FORMAT_NV21 = 0x3132564e,
++ /**
++ * 2 plane YCbCr Cr:Cb format, 2x1 subsampled Cr:Cb plane
++ */
++ WL_SHM_FORMAT_NV16 = 0x3631564e,
++ /**
++ * 2 plane YCbCr Cb:Cr format, 2x1 subsampled Cb:Cr plane
++ */
++ WL_SHM_FORMAT_NV61 = 0x3136564e,
++ /**
++ * 3 plane YCbCr format, 4x4 subsampled Cb (1) and Cr (2) planes
++ */
++ WL_SHM_FORMAT_YUV410 = 0x39565559,
++ /**
++ * 3 plane YCbCr format, 4x4 subsampled Cr (1) and Cb (2) planes
++ */
++ WL_SHM_FORMAT_YVU410 = 0x39555659,
++ /**
++ * 3 plane YCbCr format, 4x1 subsampled Cb (1) and Cr (2) planes
++ */
++ WL_SHM_FORMAT_YUV411 = 0x31315559,
++ /**
++ * 3 plane YCbCr format, 4x1 subsampled Cr (1) and Cb (2) planes
++ */
++ WL_SHM_FORMAT_YVU411 = 0x31315659,
++ /**
++ * 3 plane YCbCr format, 2x2 subsampled Cb (1) and Cr (2) planes
++ */
++ WL_SHM_FORMAT_YUV420 = 0x32315559,
++ /**
++ * 3 plane YCbCr format, 2x2 subsampled Cr (1) and Cb (2) planes
++ */
++ WL_SHM_FORMAT_YVU420 = 0x32315659,
++ /**
++ * 3 plane YCbCr format, 2x1 subsampled Cb (1) and Cr (2) planes
++ */
++ WL_SHM_FORMAT_YUV422 = 0x36315559,
++ /**
++ * 3 plane YCbCr format, 2x1 subsampled Cr (1) and Cb (2) planes
++ */
++ WL_SHM_FORMAT_YVU422 = 0x36315659,
++ /**
++ * 3 plane YCbCr format, non-subsampled Cb (1) and Cr (2) planes
++ */
++ WL_SHM_FORMAT_YUV444 = 0x34325559,
++ /**
++ * 3 plane YCbCr format, non-subsampled Cr (1) and Cb (2) planes
++ */
++ WL_SHM_FORMAT_YVU444 = 0x34325659,
++};
++#endif /* WL_SHM_FORMAT_ENUM */
++
++/**
++ * @ingroup iface_wl_shm
++ * @struct wl_shm_interface
++ */
++struct wl_shm_interface {
++ /**
++ * create a shm pool
++ *
++ * Create a new wl_shm_pool object.
++ *
++ * The pool can be used to create shared memory based buffer
++ * objects. The server will mmap size bytes of the passed file
++ * descriptor, to use as backing memory for the pool.
++ * @param id pool to create
++ * @param fd file descriptor for the pool
++ * @param size pool size, in bytes
++ */
++ void (*create_pool)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t id,
++ int32_t fd,
++ int32_t size);
++};
++
++#define WL_SHM_FORMAT 0
++
++/**
++ * @ingroup iface_wl_shm
++ */
++#define WL_SHM_FORMAT_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_shm
++ */
++#define WL_SHM_CREATE_POOL_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_shm
++ * Sends an format event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param format buffer pixel format
++ */
++static inline void
++wl_shm_send_format(struct wl_resource *resource_, uint32_t format)
++{
++ wl_resource_post_event(resource_, WL_SHM_FORMAT, format);
++}
++
++/**
++ * @ingroup iface_wl_buffer
++ * @struct wl_buffer_interface
++ */
++struct wl_buffer_interface {
++ /**
++ * destroy a buffer
++ *
++ * Destroy a buffer. If and how you need to release the backing
++ * storage is defined by the buffer factory interface.
++ *
++ * For possible side-effects to a surface, see wl_surface.attach.
++ */
++ void (*destroy)(struct wl_client *client,
++ struct wl_resource *resource);
++};
++
++#define WL_BUFFER_RELEASE 0
++
++/**
++ * @ingroup iface_wl_buffer
++ */
++#define WL_BUFFER_RELEASE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_buffer
++ */
++#define WL_BUFFER_DESTROY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_buffer
++ * Sends an release event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_buffer_send_release(struct wl_resource *resource_)
++{
++ wl_resource_post_event(resource_, WL_BUFFER_RELEASE);
++}
++
++#ifndef WL_DATA_OFFER_ERROR_ENUM
++#define WL_DATA_OFFER_ERROR_ENUM
++enum wl_data_offer_error {
++ /**
++ * finish request was called untimely
++ */
++ WL_DATA_OFFER_ERROR_INVALID_FINISH = 0,
++ /**
++ * action mask contains invalid values
++ */
++ WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK = 1,
++ /**
++ * action argument has an invalid value
++ */
++ WL_DATA_OFFER_ERROR_INVALID_ACTION = 2,
++ /**
++ * offer doesn't accept this request
++ */
++ WL_DATA_OFFER_ERROR_INVALID_OFFER = 3,
++};
++#endif /* WL_DATA_OFFER_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_data_offer
++ * @struct wl_data_offer_interface
++ */
++struct wl_data_offer_interface {
++ /**
++ * accept one of the offered mime types
++ *
++ * Indicate that the client can accept the given mime type, or
++ * NULL for not accepted.
++ *
++ * For objects of version 2 or older, this request is used by the
++ * client to give feedback whether the client can receive the given
++ * mime type, or NULL if none is accepted; the feedback does not
++ * determine whether the drag-and-drop operation succeeds or not.
++ *
++ * For objects of version 3 or newer, this request determines the
++ * final result of the drag-and-drop operation. If the end result
++ * is that no mime types were accepted, the drag-and-drop operation
++ * will be cancelled and the corresponding drag source will receive
++ * wl_data_source.cancelled. Clients may still use this event in
++ * conjunction with wl_data_source.action for feedback.
++ * @param serial serial number of the accept request
++ * @param mime_type mime type accepted by the client
++ */
++ void (*accept)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t serial,
++ const char *mime_type);
++ /**
++ * request that the data is transferred
++ *
++ * To transfer the offered data, the client issues this request
++ * and indicates the mime type it wants to receive. The transfer
++ * happens through the passed file descriptor (typically created
++ * with the pipe system call). The source client writes the data in
++ * the mime type representation requested and then closes the file
++ * descriptor.
++ *
++ * The receiving client reads from the read end of the pipe until
++ * EOF and then closes its end, at which point the transfer is
++ * complete.
++ *
++ * This request may happen multiple times for different mime types,
++ * both before and after wl_data_device.drop. Drag-and-drop
++ * destination clients may preemptively fetch data or examine it
++ * more closely to determine acceptance.
++ * @param mime_type mime type desired by receiver
++ * @param fd file descriptor for data transfer
++ */
++ void (*receive)(struct wl_client *client,
++ struct wl_resource *resource,
++ const char *mime_type,
++ int32_t fd);
++ /**
++ * destroy data offer
++ *
++ * Destroy the data offer.
++ */
++ void (*destroy)(struct wl_client *client,
++ struct wl_resource *resource);
++ /**
++ * the offer will no longer be used
++ *
++ * Notifies the compositor that the drag destination successfully
++ * finished the drag-and-drop operation.
++ *
++ * Upon receiving this request, the compositor will emit
++ * wl_data_source.dnd_finished on the drag source client.
++ *
++ * It is a client error to perform other requests than
++ * wl_data_offer.destroy after this one. It is also an error to
++ * perform this request after a NULL mime type has been set in
++ * wl_data_offer.accept or no action was received through
++ * wl_data_offer.action.
++ * @since 3
++ */
++ void (*finish)(struct wl_client *client,
++ struct wl_resource *resource);
++ /**
++ * set the available/preferred drag-and-drop actions
++ *
++ * Sets the actions that the destination side client supports for
++ * this operation. This request may trigger the emission of
++ * wl_data_source.action and wl_data_offer.action events if the
++ * compositor needs to change the selected action.
++ *
++ * This request can be called multiple times throughout the
++ * drag-and-drop operation, typically in response to
++ * wl_data_device.enter or wl_data_device.motion events.
++ *
++ * This request determines the final result of the drag-and-drop
++ * operation. If the end result is that no action is accepted, the
++ * drag source will receive wl_drag_source.cancelled.
++ *
++ * The dnd_actions argument must contain only values expressed in
++ * the wl_data_device_manager.dnd_actions enum, and the
++ * preferred_action argument must only contain one of those values
++ * set, otherwise it will result in a protocol error.
++ *
++ * While managing an "ask" action, the destination drag-and-drop
++ * client may perform further wl_data_offer.receive requests, and
++ * is expected to perform one last wl_data_offer.set_actions
++ * request with a preferred action other than "ask" (and optionally
++ * wl_data_offer.accept) before requesting wl_data_offer.finish, in
++ * order to convey the action selected by the user. If the
++ * preferred action is not in the wl_data_offer.source_actions
++ * mask, an error will be raised.
++ *
++ * If the "ask" action is dismissed (e.g. user cancellation), the
++ * client is expected to perform wl_data_offer.destroy right away.
++ *
++ * This request can only be made on drag-and-drop offers, a
++ * protocol error will be raised otherwise.
++ * @param dnd_actions actions supported by the destination client
++ * @param preferred_action action preferred by the destination client
++ * @since 3
++ */
++ void (*set_actions)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t dnd_actions,
++ uint32_t preferred_action);
++};
++
++#define WL_DATA_OFFER_OFFER 0
++#define WL_DATA_OFFER_SOURCE_ACTIONS 1
++#define WL_DATA_OFFER_ACTION 2
++
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_OFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_ACTION_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_ACCEPT_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_RECEIVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_FINISH_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_data_offer
++ * Sends an offer event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param mime_type offered mime type
++ */
++static inline void
++wl_data_offer_send_offer(struct wl_resource *resource_, const char *mime_type)
++{
++ wl_resource_post_event(resource_, WL_DATA_OFFER_OFFER, mime_type);
++}
++
++/**
++ * @ingroup iface_wl_data_offer
++ * Sends an source_actions event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param source_actions actions offered by the data source
++ */
++static inline void
++wl_data_offer_send_source_actions(struct wl_resource *resource_, uint32_t source_actions)
++{
++ wl_resource_post_event(resource_, WL_DATA_OFFER_SOURCE_ACTIONS, source_actions);
++}
++
++/**
++ * @ingroup iface_wl_data_offer
++ * Sends an action event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param dnd_action action selected by the compositor
++ */
++static inline void
++wl_data_offer_send_action(struct wl_resource *resource_, uint32_t dnd_action)
++{
++ wl_resource_post_event(resource_, WL_DATA_OFFER_ACTION, dnd_action);
++}
++
++#ifndef WL_DATA_SOURCE_ERROR_ENUM
++#define WL_DATA_SOURCE_ERROR_ENUM
++enum wl_data_source_error {
++ /**
++ * action mask contains invalid values
++ */
++ WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK = 0,
++ /**
++ * source doesn't accept this request
++ */
++ WL_DATA_SOURCE_ERROR_INVALID_SOURCE = 1,
++};
++#endif /* WL_DATA_SOURCE_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_data_source
++ * @struct wl_data_source_interface
++ */
++struct wl_data_source_interface {
++ /**
++ * add an offered mime type
++ *
++ * This request adds a mime type to the set of mime types
++ * advertised to targets. Can be called several times to offer
++ * multiple types.
++ * @param mime_type mime type offered by the data source
++ */
++ void (*offer)(struct wl_client *client,
++ struct wl_resource *resource,
++ const char *mime_type);
++ /**
++ * destroy the data source
++ *
++ * Destroy the data source.
++ */
++ void (*destroy)(struct wl_client *client,
++ struct wl_resource *resource);
++ /**
++ * set the available drag-and-drop actions
++ *
++ * Sets the actions that the source side client supports for this
++ * operation. This request may trigger wl_data_source.action and
++ * wl_data_offer.action events if the compositor needs to change
++ * the selected action.
++ *
++ * The dnd_actions argument must contain only values expressed in
++ * the wl_data_device_manager.dnd_actions enum, otherwise it will
++ * result in a protocol error.
++ *
++ * This request must be made once only, and can only be made on
++ * sources used in drag-and-drop, so it must be performed before
++ * wl_data_device.start_drag. Attempting to use the source other
++ * than for drag-and-drop will raise a protocol error.
++ * @param dnd_actions actions supported by the data source
++ * @since 3
++ */
++ void (*set_actions)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t dnd_actions);
++};
++
++#define WL_DATA_SOURCE_TARGET 0
++#define WL_DATA_SOURCE_SEND 1
++#define WL_DATA_SOURCE_CANCELLED 2
++#define WL_DATA_SOURCE_DND_DROP_PERFORMED 3
++#define WL_DATA_SOURCE_DND_FINISHED 4
++#define WL_DATA_SOURCE_ACTION 5
++
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_TARGET_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_SEND_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_CANCELLED_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_ACTION_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_OFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_data_source
++ * Sends an target event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param mime_type mime type accepted by the target
++ */
++static inline void
++wl_data_source_send_target(struct wl_resource *resource_, const char *mime_type)
++{
++ wl_resource_post_event(resource_, WL_DATA_SOURCE_TARGET, mime_type);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ * Sends an send event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param mime_type mime type for the data
++ * @param fd file descriptor for the data
++ */
++static inline void
++wl_data_source_send_send(struct wl_resource *resource_, const char *mime_type, int32_t fd)
++{
++ wl_resource_post_event(resource_, WL_DATA_SOURCE_SEND, mime_type, fd);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ * Sends an cancelled event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_data_source_send_cancelled(struct wl_resource *resource_)
++{
++ wl_resource_post_event(resource_, WL_DATA_SOURCE_CANCELLED);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ * Sends an dnd_drop_performed event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_data_source_send_dnd_drop_performed(struct wl_resource *resource_)
++{
++ wl_resource_post_event(resource_, WL_DATA_SOURCE_DND_DROP_PERFORMED);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ * Sends an dnd_finished event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_data_source_send_dnd_finished(struct wl_resource *resource_)
++{
++ wl_resource_post_event(resource_, WL_DATA_SOURCE_DND_FINISHED);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ * Sends an action event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param dnd_action action selected by the compositor
++ */
++static inline void
++wl_data_source_send_action(struct wl_resource *resource_, uint32_t dnd_action)
++{
++ wl_resource_post_event(resource_, WL_DATA_SOURCE_ACTION, dnd_action);
++}
++
++#ifndef WL_DATA_DEVICE_ERROR_ENUM
++#define WL_DATA_DEVICE_ERROR_ENUM
++enum wl_data_device_error {
++ /**
++ * given wl_surface has another role
++ */
++ WL_DATA_DEVICE_ERROR_ROLE = 0,
++};
++#endif /* WL_DATA_DEVICE_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_data_device
++ * @struct wl_data_device_interface
++ */
++struct wl_data_device_interface {
++ /**
++ * start drag-and-drop operation
++ *
++ * This request asks the compositor to start a drag-and-drop
++ * operation on behalf of the client.
++ *
++ * The source argument is the data source that provides the data
++ * for the eventual data transfer. If source is NULL, enter, leave
++ * and motion events are sent only to the client that initiated the
++ * drag and the client is expected to handle the data passing
++ * internally.
++ *
++ * The origin surface is the surface where the drag originates and
++ * the client must have an active implicit grab that matches the
++ * serial.
++ *
++ * The icon surface is an optional (can be NULL) surface that
++ * provides an icon to be moved around with the cursor. Initially,
++ * the top-left corner of the icon surface is placed at the cursor
++ * hotspot, but subsequent wl_surface.attach request can move the
++ * relative position. Attach requests must be confirmed with
++ * wl_surface.commit as usual. The icon surface is given the role
++ * of a drag-and-drop icon. If the icon surface already has another
++ * role, it raises a protocol error.
++ *
++ * The current and pending input regions of the icon wl_surface are
++ * cleared, and wl_surface.set_input_region is ignored until the
++ * wl_surface is no longer used as the icon surface. When the use
++ * as an icon ends, the current and pending input regions become
++ * undefined, and the wl_surface is unmapped.
++ * @param source data source for the eventual transfer
++ * @param origin surface where the drag originates
++ * @param icon drag-and-drop icon surface
++ * @param serial serial number of the implicit grab on the origin
++ */
++ void (*start_drag)(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *source,
++ struct wl_resource *origin,
++ struct wl_resource *icon,
++ uint32_t serial);
++ /**
++ * copy data to the selection
++ *
++ * This request asks the compositor to set the selection to the
++ * data from the source on behalf of the client.
++ *
++ * To unset the selection, set the source to NULL.
++ * @param source data source for the selection
++ * @param serial serial number of the event that triggered this request
++ */
++ void (*set_selection)(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *source,
++ uint32_t serial);
++ /**
++ * destroy data device
++ *
++ * This request destroys the data device.
++ * @since 2
++ */
++ void (*release)(struct wl_client *client,
++ struct wl_resource *resource);
++};
++
++#define WL_DATA_DEVICE_DATA_OFFER 0
++#define WL_DATA_DEVICE_ENTER 1
++#define WL_DATA_DEVICE_LEAVE 2
++#define WL_DATA_DEVICE_MOTION 3
++#define WL_DATA_DEVICE_DROP 4
++#define WL_DATA_DEVICE_SELECTION 5
++
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_DATA_OFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_LEAVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_MOTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_DROP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_SELECTION_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_START_DRAG_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_SET_SELECTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_RELEASE_SINCE_VERSION 2
++
++/**
++ * @ingroup iface_wl_data_device
++ * Sends an data_offer event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param id the new data_offer object
++ */
++static inline void
++wl_data_device_send_data_offer(struct wl_resource *resource_, struct wl_resource *id)
++{
++ wl_resource_post_event(resource_, WL_DATA_DEVICE_DATA_OFFER, id);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ * Sends an enter event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the enter event
++ * @param surface client surface entered
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ * @param id source data_offer object
++ */
++static inline void
++wl_data_device_send_enter(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface, wl_fixed_t x, wl_fixed_t y, struct wl_resource *id)
++{
++ wl_resource_post_event(resource_, WL_DATA_DEVICE_ENTER, serial, surface, x, y, id);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ * Sends an leave event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_data_device_send_leave(struct wl_resource *resource_)
++{
++ wl_resource_post_event(resource_, WL_DATA_DEVICE_LEAVE);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ * Sends an motion event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param time timestamp with millisecond granularity
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ */
++static inline void
++wl_data_device_send_motion(struct wl_resource *resource_, uint32_t time, wl_fixed_t x, wl_fixed_t y)
++{
++ wl_resource_post_event(resource_, WL_DATA_DEVICE_MOTION, time, x, y);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ * Sends an drop event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_data_device_send_drop(struct wl_resource *resource_)
++{
++ wl_resource_post_event(resource_, WL_DATA_DEVICE_DROP);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ * Sends an selection event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param id selection data_offer object
++ */
++static inline void
++wl_data_device_send_selection(struct wl_resource *resource_, struct wl_resource *id)
++{
++ wl_resource_post_event(resource_, WL_DATA_DEVICE_SELECTION, id);
++}
++
++#ifndef WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM
++#define WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM
++/**
++ * @ingroup iface_wl_data_device_manager
++ * drag and drop actions
++ *
++ * This is a bitmask of the available/preferred actions in a
++ * drag-and-drop operation.
++ *
++ * In the compositor, the selected action is a result of matching the
++ * actions offered by the source and destination sides. "action" events
++ * with a "none" action will be sent to both source and destination if
++ * there is no match. All further checks will effectively happen on
++ * (source actions ∩ destination actions).
++ *
++ * In addition, compositors may also pick different actions in
++ * reaction to key modifiers being pressed. One common design that
++ * is used in major toolkits (and the behavior recommended for
++ * compositors) is:
++ *
++ * - If no modifiers are pressed, the first match (in bit order)
++ * will be used.
++ * - Pressing Shift selects "move", if enabled in the mask.
++ * - Pressing Control selects "copy", if enabled in the mask.
++ *
++ * Behavior beyond that is considered implementation-dependent.
++ * Compositors may for example bind other modifiers (like Alt/Meta)
++ * or drags initiated with other buttons than BTN_LEFT to specific
++ * actions (e.g. "ask").
++ */
++enum wl_data_device_manager_dnd_action {
++ /**
++ * no action
++ */
++ WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE = 0,
++ /**
++ * copy action
++ */
++ WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY = 1,
++ /**
++ * move action
++ */
++ WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE = 2,
++ /**
++ * ask action
++ */
++ WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK = 4,
++};
++#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM */
++
++/**
++ * @ingroup iface_wl_data_device_manager
++ * @struct wl_data_device_manager_interface
++ */
++struct wl_data_device_manager_interface {
++ /**
++ * create a new data source
++ *
++ * Create a new data source.
++ * @param id data source to create
++ */
++ void (*create_data_source)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t id);
++ /**
++ * create a new data device
++ *
++ * Create a new data device for a given seat.
++ * @param id data device to create
++ * @param seat seat associated with the data device
++ */
++ void (*get_data_device)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t id,
++ struct wl_resource *seat);
++};
++
++
++/**
++ * @ingroup iface_wl_data_device_manager
++ */
++#define WL_DATA_DEVICE_MANAGER_CREATE_DATA_SOURCE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device_manager
++ */
++#define WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE_SINCE_VERSION 1
++
++#ifndef WL_SHELL_ERROR_ENUM
++#define WL_SHELL_ERROR_ENUM
++enum wl_shell_error {
++ /**
++ * given wl_surface has another role
++ */
++ WL_SHELL_ERROR_ROLE = 0,
++};
++#endif /* WL_SHELL_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_shell
++ * @struct wl_shell_interface
++ */
++struct wl_shell_interface {
++ /**
++ * create a shell surface from a surface
++ *
++ * Create a shell surface for an existing surface. This gives the
++ * wl_surface the role of a shell surface. If the wl_surface
++ * already has another role, it raises a protocol error.
++ *
++ * Only one shell surface can be associated with a given surface.
++ * @param id shell surface to create
++ * @param surface surface to be given the shell surface role
++ */
++ void (*get_shell_surface)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t id,
++ struct wl_resource *surface);
++};
++
++
++/**
++ * @ingroup iface_wl_shell
++ */
++#define WL_SHELL_GET_SHELL_SURFACE_SINCE_VERSION 1
++
++#ifndef WL_SHELL_SURFACE_RESIZE_ENUM
++#define WL_SHELL_SURFACE_RESIZE_ENUM
++/**
++ * @ingroup iface_wl_shell_surface
++ * edge values for resizing
++ *
++ * These values are used to indicate which edge of a surface
++ * is being dragged in a resize operation. The server may
++ * use this information to adapt its behavior, e.g. choose
++ * an appropriate cursor image.
++ */
++enum wl_shell_surface_resize {
++ /**
++ * no edge
++ */
++ WL_SHELL_SURFACE_RESIZE_NONE = 0,
++ /**
++ * top edge
++ */
++ WL_SHELL_SURFACE_RESIZE_TOP = 1,
++ /**
++ * bottom edge
++ */
++ WL_SHELL_SURFACE_RESIZE_BOTTOM = 2,
++ /**
++ * left edge
++ */
++ WL_SHELL_SURFACE_RESIZE_LEFT = 4,
++ /**
++ * top and left edges
++ */
++ WL_SHELL_SURFACE_RESIZE_TOP_LEFT = 5,
++ /**
++ * bottom and left edges
++ */
++ WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT = 6,
++ /**
++ * right edge
++ */
++ WL_SHELL_SURFACE_RESIZE_RIGHT = 8,
++ /**
++ * top and right edges
++ */
++ WL_SHELL_SURFACE_RESIZE_TOP_RIGHT = 9,
++ /**
++ * bottom and right edges
++ */
++ WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT = 10,
++};
++#endif /* WL_SHELL_SURFACE_RESIZE_ENUM */
++
++#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM
++#define WL_SHELL_SURFACE_TRANSIENT_ENUM
++/**
++ * @ingroup iface_wl_shell_surface
++ * details of transient behaviour
++ *
++ * These flags specify details of the expected behaviour
++ * of transient surfaces. Used in the set_transient request.
++ */
++enum wl_shell_surface_transient {
++ /**
++ * do not set keyboard focus
++ */
++ WL_SHELL_SURFACE_TRANSIENT_INACTIVE = 0x1,
++};
++#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM */
++
++#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
++#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
++/**
++ * @ingroup iface_wl_shell_surface
++ * different method to set the surface fullscreen
++ *
++ * Hints to indicate to the compositor how to deal with a conflict
++ * between the dimensions of the surface and the dimensions of the
++ * output. The compositor is free to ignore this parameter.
++ */
++enum wl_shell_surface_fullscreen_method {
++ /**
++ * no preference, apply default policy
++ */
++ WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT = 0,
++ /**
++ * scale, preserve the surface's aspect ratio and center on output
++ */
++ WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE = 1,
++ /**
++ * switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch
++ */
++ WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER = 2,
++ /**
++ * no upscaling, center on output and add black borders to compensate size mismatch
++ */
++ WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL = 3,
++};
++#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM */
++
++/**
++ * @ingroup iface_wl_shell_surface
++ * @struct wl_shell_surface_interface
++ */
++struct wl_shell_surface_interface {
++ /**
++ * respond to a ping event
++ *
++ * A client must respond to a ping event with a pong request or
++ * the client may be deemed unresponsive.
++ * @param serial serial number of the ping event
++ */
++ void (*pong)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t serial);
++ /**
++ * start an interactive move
++ *
++ * Start a pointer-driven move of the surface.
++ *
++ * This request must be used in response to a button press event.
++ * The server may ignore move requests depending on the state of
++ * the surface (e.g. fullscreen or maximized).
++ * @param seat seat whose pointer is used
++ * @param serial serial number of the implicit grab on the pointer
++ */
++ void (*move)(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *seat,
++ uint32_t serial);
++ /**
++ * start an interactive resize
++ *
++ * Start a pointer-driven resizing of the surface.
++ *
++ * This request must be used in response to a button press event.
++ * The server may ignore resize requests depending on the state of
++ * the surface (e.g. fullscreen or maximized).
++ * @param seat seat whose pointer is used
++ * @param serial serial number of the implicit grab on the pointer
++ * @param edges which edge or corner is being dragged
++ */
++ void (*resize)(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *seat,
++ uint32_t serial,
++ uint32_t edges);
++ /**
++ * make the surface a toplevel surface
++ *
++ * Map the surface as a toplevel surface.
++ *
++ * A toplevel surface is not fullscreen, maximized or transient.
++ */
++ void (*set_toplevel)(struct wl_client *client,
++ struct wl_resource *resource);
++ /**
++ * make the surface a transient surface
++ *
++ * Map the surface relative to an existing surface.
++ *
++ * The x and y arguments specify the location of the upper left
++ * corner of the surface relative to the upper left corner of the
++ * parent surface, in surface-local coordinates.
++ *
++ * The flags argument controls details of the transient behaviour.
++ * @param parent parent surface
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ * @param flags transient surface behavior
++ */
++ void (*set_transient)(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *parent,
++ int32_t x,
++ int32_t y,
++ uint32_t flags);
++ /**
++ * make the surface a fullscreen surface
++ *
++ * Map the surface as a fullscreen surface.
++ *
++ * If an output parameter is given then the surface will be made
++ * fullscreen on that output. If the client does not specify the
++ * output then the compositor will apply its policy - usually
++ * choosing the output on which the surface has the biggest surface
++ * area.
++ *
++ * The client may specify a method to resolve a size conflict
++ * between the output size and the surface size - this is provided
++ * through the method parameter.
++ *
++ * The framerate parameter is used only when the method is set to
++ * "driver", to indicate the preferred framerate. A value of 0
++ * indicates that the client does not care about framerate. The
++ * framerate is specified in mHz, that is framerate of 60000 is
++ * 60Hz.
++ *
++ * A method of "scale" or "driver" implies a scaling operation of
++ * the surface, either via a direct scaling operation or a change
++ * of the output mode. This will override any kind of output
++ * scaling, so that mapping a surface with a buffer size equal to
++ * the mode can fill the screen independent of buffer_scale.
++ *
++ * A method of "fill" means we don't scale up the buffer, however
++ * any output scale is applied. This means that you may run into an
++ * edge case where the application maps a buffer with the same size
++ * of the output mode but buffer_scale 1 (thus making a surface
++ * larger than the output). In this case it is allowed to downscale
++ * the results to fit the screen.
++ *
++ * The compositor must reply to this request with a configure event
++ * with the dimensions for the output on which the surface will be
++ * made fullscreen.
++ * @param method method for resolving size conflict
++ * @param framerate framerate in mHz
++ * @param output output on which the surface is to be fullscreen
++ */
++ void (*set_fullscreen)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t method,
++ uint32_t framerate,
++ struct wl_resource *output);
++ /**
++ * make the surface a popup surface
++ *
++ * Map the surface as a popup.
++ *
++ * A popup surface is a transient surface with an added pointer
++ * grab.
++ *
++ * An existing implicit grab will be changed to owner-events mode,
++ * and the popup grab will continue after the implicit grab ends
++ * (i.e. releasing the mouse button does not cause the popup to be
++ * unmapped).
++ *
++ * The popup grab continues until the window is destroyed or a
++ * mouse button is pressed in any other client's window. A click in
++ * any of the client's surfaces is reported as normal, however,
++ * clicks in other clients' surfaces will be discarded and trigger
++ * the callback.
++ *
++ * The x and y arguments specify the location of the upper left
++ * corner of the surface relative to the upper left corner of the
++ * parent surface, in surface-local coordinates.
++ * @param seat seat whose pointer is used
++ * @param serial serial number of the implicit grab on the pointer
++ * @param parent parent surface
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ * @param flags transient surface behavior
++ */
++ void (*set_popup)(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *seat,
++ uint32_t serial,
++ struct wl_resource *parent,
++ int32_t x,
++ int32_t y,
++ uint32_t flags);
++ /**
++ * make the surface a maximized surface
++ *
++ * Map the surface as a maximized surface.
++ *
++ * If an output parameter is given then the surface will be
++ * maximized on that output. If the client does not specify the
++ * output then the compositor will apply its policy - usually
++ * choosing the output on which the surface has the biggest surface
++ * area.
++ *
++ * The compositor will reply with a configure event telling the
++ * expected new surface size. The operation is completed on the
++ * next buffer attach to this surface.
++ *
++ * A maximized surface typically fills the entire output it is
++ * bound to, except for desktop elements such as panels. This is
++ * the main difference between a maximized shell surface and a
++ * fullscreen shell surface.
++ *
++ * The details depend on the compositor implementation.
++ * @param output output on which the surface is to be maximized
++ */
++ void (*set_maximized)(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *output);
++ /**
++ * set surface title
++ *
++ * Set a short title for the surface.
++ *
++ * This string may be used to identify the surface in a task bar,
++ * window list, or other user interface elements provided by the
++ * compositor.
++ *
++ * The string must be encoded in UTF-8.
++ * @param title surface title
++ */
++ void (*set_title)(struct wl_client *client,
++ struct wl_resource *resource,
++ const char *title);
++ /**
++ * set surface class
++ *
++ * Set a class for the surface.
++ *
++ * The surface class identifies the general class of applications
++ * to which the surface belongs. A common convention is to use the
++ * file name (or the full path if it is a non-standard location) of
++ * the application's .desktop file as the class.
++ * @param class_ surface class
++ */
++ void (*set_class)(struct wl_client *client,
++ struct wl_resource *resource,
++ const char *class_);
++};
++
++#define WL_SHELL_SURFACE_PING 0
++#define WL_SHELL_SURFACE_CONFIGURE 1
++#define WL_SHELL_SURFACE_POPUP_DONE 2
++
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_PING_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_CONFIGURE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_POPUP_DONE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_PONG_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_MOVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_RESIZE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_TOPLEVEL_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_TRANSIENT_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_FULLSCREEN_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_POPUP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_MAXIMIZED_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_TITLE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_CLASS_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_shell_surface
++ * Sends an ping event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the ping
++ */
++static inline void
++wl_shell_surface_send_ping(struct wl_resource *resource_, uint32_t serial)
++{
++ wl_resource_post_event(resource_, WL_SHELL_SURFACE_PING, serial);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ * Sends an configure event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param edges how the surface was resized
++ * @param width new width of the surface
++ * @param height new height of the surface
++ */
++static inline void
++wl_shell_surface_send_configure(struct wl_resource *resource_, uint32_t edges, int32_t width, int32_t height)
++{
++ wl_resource_post_event(resource_, WL_SHELL_SURFACE_CONFIGURE, edges, width, height);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ * Sends an popup_done event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_shell_surface_send_popup_done(struct wl_resource *resource_)
++{
++ wl_resource_post_event(resource_, WL_SHELL_SURFACE_POPUP_DONE);
++}
++
++#ifndef WL_SURFACE_ERROR_ENUM
++#define WL_SURFACE_ERROR_ENUM
++/**
++ * @ingroup iface_wl_surface
++ * wl_surface error values
++ *
++ * These errors can be emitted in response to wl_surface requests.
++ */
++enum wl_surface_error {
++ /**
++ * buffer scale value is invalid
++ */
++ WL_SURFACE_ERROR_INVALID_SCALE = 0,
++ /**
++ * buffer transform value is invalid
++ */
++ WL_SURFACE_ERROR_INVALID_TRANSFORM = 1,
++};
++#endif /* WL_SURFACE_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_surface
++ * @struct wl_surface_interface
++ */
++struct wl_surface_interface {
++ /**
++ * delete surface
++ *
++ * Deletes the surface and invalidates its object ID.
++ */
++ void (*destroy)(struct wl_client *client,
++ struct wl_resource *resource);
++ /**
++ * set the surface contents
++ *
++ * Set a buffer as the content of this surface.
++ *
++ * The new size of the surface is calculated based on the buffer
++ * size transformed by the inverse buffer_transform and the inverse
++ * buffer_scale. This means that the supplied buffer must be an
++ * integer multiple of the buffer_scale.
++ *
++ * The x and y arguments specify the location of the new pending
++ * buffer's upper left corner, relative to the current buffer's
++ * upper left corner, in surface-local coordinates. In other words,
++ * the x and y, combined with the new surface size define in which
++ * directions the surface's size changes.
++ *
++ * Surface contents are double-buffered state, see
++ * wl_surface.commit.
++ *
++ * The initial surface contents are void; there is no content.
++ * wl_surface.attach assigns the given wl_buffer as the pending
++ * wl_buffer. wl_surface.commit makes the pending wl_buffer the new
++ * surface contents, and the size of the surface becomes the size
++ * calculated from the wl_buffer, as described above. After commit,
++ * there is no pending buffer until the next attach.
++ *
++ * Committing a pending wl_buffer allows the compositor to read the
++ * pixels in the wl_buffer. The compositor may access the pixels at
++ * any time after the wl_surface.commit request. When the
++ * compositor will not access the pixels anymore, it will send the
++ * wl_buffer.release event. Only after receiving wl_buffer.release,
++ * the client may reuse the wl_buffer. A wl_buffer that has been
++ * attached and then replaced by another attach instead of
++ * committed will not receive a release event, and is not used by
++ * the compositor.
++ *
++ * Destroying the wl_buffer after wl_buffer.release does not change
++ * the surface contents. However, if the client destroys the
++ * wl_buffer before receiving the wl_buffer.release event, the
++ * surface contents become undefined immediately.
++ *
++ * If wl_surface.attach is sent with a NULL wl_buffer, the
++ * following wl_surface.commit will remove the surface content.
++ * @param buffer buffer of surface contents
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ */
++ void (*attach)(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *buffer,
++ int32_t x,
++ int32_t y);
++ /**
++ * mark part of the surface damaged
++ *
++ * This request is used to describe the regions where the pending
++ * buffer is different from the current surface contents, and where
++ * the surface therefore needs to be repainted. The compositor
++ * ignores the parts of the damage that fall outside of the
++ * surface.
++ *
++ * Damage is double-buffered state, see wl_surface.commit.
++ *
++ * The damage rectangle is specified in surface-local coordinates,
++ * where x and y specify the upper left corner of the damage
++ * rectangle.
++ *
++ * The initial value for pending damage is empty: no damage.
++ * wl_surface.damage adds pending damage: the new pending damage is
++ * the union of old pending damage and the given rectangle.
++ *
++ * wl_surface.commit assigns pending damage as the current damage,
++ * and clears pending damage. The server will clear the current
++ * damage as it repaints the surface.
++ *
++ * Alternatively, damage can be posted with
++ * wl_surface.damage_buffer which uses buffer coordinates instead
++ * of surface coordinates, and is probably the preferred and
++ * intuitive way of doing this.
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ * @param width width of damage rectangle
++ * @param height height of damage rectangle
++ */
++ void (*damage)(struct wl_client *client,
++ struct wl_resource *resource,
++ int32_t x,
++ int32_t y,
++ int32_t width,
++ int32_t height);
++ /**
++ * request a frame throttling hint
++ *
++ * Request a notification when it is a good time to start drawing
++ * a new frame, by creating a frame callback. This is useful for
++ * throttling redrawing operations, and driving animations.
++ *
++ * When a client is animating on a wl_surface, it can use the
++ * 'frame' request to get notified when it is a good time to draw
++ * and commit the next frame of animation. If the client commits an
++ * update earlier than that, it is likely that some updates will
++ * not make it to the display, and the client is wasting resources
++ * by drawing too often.
++ *
++ * The frame request will take effect on the next
++ * wl_surface.commit. The notification will only be posted for one
++ * frame unless requested again. For a wl_surface, the
++ * notifications are posted in the order the frame requests were
++ * committed.
++ *
++ * The server must send the notifications so that a client will not
++ * send excessive updates, while still allowing the highest
++ * possible update rate for clients that wait for the reply before
++ * drawing again. The server should give some time for the client
++ * to draw and commit after sending the frame callback events to
++ * let it hit the next output refresh.
++ *
++ * A server should avoid signaling the frame callbacks if the
++ * surface is not visible in any way, e.g. the surface is
++ * off-screen, or completely obscured by other opaque surfaces.
++ *
++ * The object returned by this request will be destroyed by the
++ * compositor after the callback is fired and as such the client
++ * must not attempt to use it after that point.
++ *
++ * The callback_data passed in the callback is the current time, in
++ * milliseconds, with an undefined base.
++ * @param callback callback object for the frame request
++ */
++ void (*frame)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t callback);
++ /**
++ * set opaque region
++ *
++ * This request sets the region of the surface that contains
++ * opaque content.
++ *
++ * The opaque region is an optimization hint for the compositor
++ * that lets it optimize the redrawing of content behind opaque
++ * regions. Setting an opaque region is not required for correct
++ * behaviour, but marking transparent content as opaque will result
++ * in repaint artifacts.
++ *
++ * The opaque region is specified in surface-local coordinates.
++ *
++ * The compositor ignores the parts of the opaque region that fall
++ * outside of the surface.
++ *
++ * Opaque region is double-buffered state, see wl_surface.commit.
++ *
++ * wl_surface.set_opaque_region changes the pending opaque region.
++ * wl_surface.commit copies the pending region to the current
++ * region. Otherwise, the pending and current regions are never
++ * changed.
++ *
++ * The initial value for an opaque region is empty. Setting the
++ * pending opaque region has copy semantics, and the wl_region
++ * object can be destroyed immediately. A NULL wl_region causes the
++ * pending opaque region to be set to empty.
++ * @param region opaque region of the surface
++ */
++ void (*set_opaque_region)(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *region);
++ /**
++ * set input region
++ *
++ * This request sets the region of the surface that can receive
++ * pointer and touch events.
++ *
++ * Input events happening outside of this region will try the next
++ * surface in the server surface stack. The compositor ignores the
++ * parts of the input region that fall outside of the surface.
++ *
++ * The input region is specified in surface-local coordinates.
++ *
++ * Input region is double-buffered state, see wl_surface.commit.
++ *
++ * wl_surface.set_input_region changes the pending input region.
++ * wl_surface.commit copies the pending region to the current
++ * region. Otherwise the pending and current regions are never
++ * changed, except cursor and icon surfaces are special cases, see
++ * wl_pointer.set_cursor and wl_data_device.start_drag.
++ *
++ * The initial value for an input region is infinite. That means
++ * the whole surface will accept input. Setting the pending input
++ * region has copy semantics, and the wl_region object can be
++ * destroyed immediately. A NULL wl_region causes the input region
++ * to be set to infinite.
++ * @param region input region of the surface
++ */
++ void (*set_input_region)(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *region);
++ /**
++ * commit pending surface state
++ *
++ * Surface state (input, opaque, and damage regions, attached
++ * buffers, etc.) is double-buffered. Protocol requests modify the
++ * pending state, as opposed to the current state in use by the
++ * compositor. A commit request atomically applies all pending
++ * state, replacing the current state. After commit, the new
++ * pending state is as documented for each related request.
++ *
++ * On commit, a pending wl_buffer is applied first, and all other
++ * state second. This means that all coordinates in double-buffered
++ * state are relative to the new wl_buffer coming into use, except
++ * for wl_surface.attach itself. If there is no pending wl_buffer,
++ * the coordinates are relative to the current surface contents.
++ *
++ * All requests that need a commit to become effective are
++ * documented to affect double-buffered state.
++ *
++ * Other interfaces may add further double-buffered surface state.
++ */
++ void (*commit)(struct wl_client *client,
++ struct wl_resource *resource);
++ /**
++ * sets the buffer transformation
++ *
++ * This request sets an optional transformation on how the
++ * compositor interprets the contents of the buffer attached to the
++ * surface. The accepted values for the transform parameter are the
++ * values for wl_output.transform.
++ *
++ * Buffer transform is double-buffered state, see
++ * wl_surface.commit.
++ *
++ * A newly created surface has its buffer transformation set to
++ * normal.
++ *
++ * wl_surface.set_buffer_transform changes the pending buffer
++ * transformation. wl_surface.commit copies the pending buffer
++ * transformation to the current one. Otherwise, the pending and
++ * current values are never changed.
++ *
++ * The purpose of this request is to allow clients to render
++ * content according to the output transform, thus permitting the
++ * compositor to use certain optimizations even if the display is
++ * rotated. Using hardware overlays and scanning out a client
++ * buffer for fullscreen surfaces are examples of such
++ * optimizations. Those optimizations are highly dependent on the
++ * compositor implementation, so the use of this request should be
++ * considered on a case-by-case basis.
++ *
++ * Note that if the transform value includes 90 or 270 degree
++ * rotation, the width of the buffer will become the surface height
++ * and the height of the buffer will become the surface width.
++ *
++ * If transform is not one of the values from the
++ * wl_output.transform enum the invalid_transform protocol error is
++ * raised.
++ * @param transform transform for interpreting buffer contents
++ * @since 2
++ */
++ void (*set_buffer_transform)(struct wl_client *client,
++ struct wl_resource *resource,
++ int32_t transform);
++ /**
++ * sets the buffer scaling factor
++ *
++ * This request sets an optional scaling factor on how the
++ * compositor interprets the contents of the buffer attached to the
++ * window.
++ *
++ * Buffer scale is double-buffered state, see wl_surface.commit.
++ *
++ * A newly created surface has its buffer scale set to 1.
++ *
++ * wl_surface.set_buffer_scale changes the pending buffer scale.
++ * wl_surface.commit copies the pending buffer scale to the current
++ * one. Otherwise, the pending and current values are never
++ * changed.
++ *
++ * The purpose of this request is to allow clients to supply higher
++ * resolution buffer data for use on high resolution outputs. It is
++ * intended that you pick the same buffer scale as the scale of the
++ * output that the surface is displayed on. This means the
++ * compositor can avoid scaling when rendering the surface on that
++ * output.
++ *
++ * Note that if the scale is larger than 1, then you have to attach
++ * a buffer that is larger (by a factor of scale in each dimension)
++ * than the desired surface size.
++ *
++ * If scale is not positive the invalid_scale protocol error is
++ * raised.
++ * @param scale positive scale for interpreting buffer contents
++ * @since 3
++ */
++ void (*set_buffer_scale)(struct wl_client *client,
++ struct wl_resource *resource,
++ int32_t scale);
++ /**
++ * mark part of the surface damaged using buffer coordinates
++ *
++ * This request is used to describe the regions where the pending
++ * buffer is different from the current surface contents, and where
++ * the surface therefore needs to be repainted. The compositor
++ * ignores the parts of the damage that fall outside of the
++ * surface.
++ *
++ * Damage is double-buffered state, see wl_surface.commit.
++ *
++ * The damage rectangle is specified in buffer coordinates, where x
++ * and y specify the upper left corner of the damage rectangle.
++ *
++ * The initial value for pending damage is empty: no damage.
++ * wl_surface.damage_buffer adds pending damage: the new pending
++ * damage is the union of old pending damage and the given
++ * rectangle.
++ *
++ * wl_surface.commit assigns pending damage as the current damage,
++ * and clears pending damage. The server will clear the current
++ * damage as it repaints the surface.
++ *
++ * This request differs from wl_surface.damage in only one way - it
++ * takes damage in buffer coordinates instead of surface-local
++ * coordinates. While this generally is more intuitive than surface
++ * coordinates, it is especially desirable when using wp_viewport
++ * or when a drawing library (like EGL) is unaware of buffer scale
++ * and buffer transform.
++ *
++ * Note: Because buffer transformation changes and damage requests
++ * may be interleaved in the protocol stream, it is impossible to
++ * determine the actual mapping between surface and buffer damage
++ * until wl_surface.commit time. Therefore, compositors wishing to
++ * take both kinds of damage into account will have to accumulate
++ * damage from the two requests separately and only transform from
++ * one to the other after receiving the wl_surface.commit.
++ * @param x buffer-local x coordinate
++ * @param y buffer-local y coordinate
++ * @param width width of damage rectangle
++ * @param height height of damage rectangle
++ * @since 4
++ */
++ void (*damage_buffer)(struct wl_client *client,
++ struct wl_resource *resource,
++ int32_t x,
++ int32_t y,
++ int32_t width,
++ int32_t height);
++};
++
++#define WL_SURFACE_ENTER 0
++#define WL_SURFACE_LEAVE 1
++
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_LEAVE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_ATTACH_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_DAMAGE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_FRAME_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_OPAQUE_REGION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_INPUT_REGION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_COMMIT_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_BUFFER_TRANSFORM_SINCE_VERSION 2
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION 4
++
++/**
++ * @ingroup iface_wl_surface
++ * Sends an enter event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param output output entered by the surface
++ */
++static inline void
++wl_surface_send_enter(struct wl_resource *resource_, struct wl_resource *output)
++{
++ wl_resource_post_event(resource_, WL_SURFACE_ENTER, output);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ * Sends an leave event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param output output left by the surface
++ */
++static inline void
++wl_surface_send_leave(struct wl_resource *resource_, struct wl_resource *output)
++{
++ wl_resource_post_event(resource_, WL_SURFACE_LEAVE, output);
++}
++
++#ifndef WL_SEAT_CAPABILITY_ENUM
++#define WL_SEAT_CAPABILITY_ENUM
++/**
++ * @ingroup iface_wl_seat
++ * seat capability bitmask
++ *
++ * This is a bitmask of capabilities this seat has; if a member is
++ * set, then it is present on the seat.
++ */
++enum wl_seat_capability {
++ /**
++ * the seat has pointer devices
++ */
++ WL_SEAT_CAPABILITY_POINTER = 1,
++ /**
++ * the seat has one or more keyboards
++ */
++ WL_SEAT_CAPABILITY_KEYBOARD = 2,
++ /**
++ * the seat has touch devices
++ */
++ WL_SEAT_CAPABILITY_TOUCH = 4,
++};
++#endif /* WL_SEAT_CAPABILITY_ENUM */
++
++/**
++ * @ingroup iface_wl_seat
++ * @struct wl_seat_interface
++ */
++struct wl_seat_interface {
++ /**
++ * return pointer object
++ *
++ * The ID provided will be initialized to the wl_pointer
++ * interface for this seat.
++ *
++ * This request only takes effect if the seat has the pointer
++ * capability, or has had the pointer capability in the past. It is
++ * a protocol violation to issue this request on a seat that has
++ * never had the pointer capability.
++ * @param id seat pointer
++ */
++ void (*get_pointer)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t id);
++ /**
++ * return keyboard object
++ *
++ * The ID provided will be initialized to the wl_keyboard
++ * interface for this seat.
++ *
++ * This request only takes effect if the seat has the keyboard
++ * capability, or has had the keyboard capability in the past. It
++ * is a protocol violation to issue this request on a seat that has
++ * never had the keyboard capability.
++ * @param id seat keyboard
++ */
++ void (*get_keyboard)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t id);
++ /**
++ * return touch object
++ *
++ * The ID provided will be initialized to the wl_touch interface
++ * for this seat.
++ *
++ * This request only takes effect if the seat has the touch
++ * capability, or has had the touch capability in the past. It is a
++ * protocol violation to issue this request on a seat that has
++ * never had the touch capability.
++ * @param id seat touch interface
++ */
++ void (*get_touch)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t id);
++ /**
++ * release the seat object
++ *
++ * Using this request a client can tell the server that it is not
++ * going to use the seat object anymore.
++ * @since 5
++ */
++ void (*release)(struct wl_client *client,
++ struct wl_resource *resource);
++};
++
++#define WL_SEAT_CAPABILITIES 0
++#define WL_SEAT_NAME 1
++
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_CAPABILITIES_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_NAME_SINCE_VERSION 2
++
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_GET_POINTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_GET_KEYBOARD_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_GET_TOUCH_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_RELEASE_SINCE_VERSION 5
++
++/**
++ * @ingroup iface_wl_seat
++ * Sends an capabilities event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param capabilities capabilities of the seat
++ */
++static inline void
++wl_seat_send_capabilities(struct wl_resource *resource_, uint32_t capabilities)
++{
++ wl_resource_post_event(resource_, WL_SEAT_CAPABILITIES, capabilities);
++}
++
++/**
++ * @ingroup iface_wl_seat
++ * Sends an name event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param name seat identifier
++ */
++static inline void
++wl_seat_send_name(struct wl_resource *resource_, const char *name)
++{
++ wl_resource_post_event(resource_, WL_SEAT_NAME, name);
++}
++
++#ifndef WL_POINTER_ERROR_ENUM
++#define WL_POINTER_ERROR_ENUM
++enum wl_pointer_error {
++ /**
++ * given wl_surface has another role
++ */
++ WL_POINTER_ERROR_ROLE = 0,
++};
++#endif /* WL_POINTER_ERROR_ENUM */
++
++#ifndef WL_POINTER_BUTTON_STATE_ENUM
++#define WL_POINTER_BUTTON_STATE_ENUM
++/**
++ * @ingroup iface_wl_pointer
++ * physical button state
++ *
++ * Describes the physical state of a button that produced the button
++ * event.
++ */
++enum wl_pointer_button_state {
++ /**
++ * the button is not pressed
++ */
++ WL_POINTER_BUTTON_STATE_RELEASED = 0,
++ /**
++ * the button is pressed
++ */
++ WL_POINTER_BUTTON_STATE_PRESSED = 1,
++};
++#endif /* WL_POINTER_BUTTON_STATE_ENUM */
++
++#ifndef WL_POINTER_AXIS_ENUM
++#define WL_POINTER_AXIS_ENUM
++/**
++ * @ingroup iface_wl_pointer
++ * axis types
++ *
++ * Describes the axis types of scroll events.
++ */
++enum wl_pointer_axis {
++ /**
++ * vertical axis
++ */
++ WL_POINTER_AXIS_VERTICAL_SCROLL = 0,
++ /**
++ * horizontal axis
++ */
++ WL_POINTER_AXIS_HORIZONTAL_SCROLL = 1,
++};
++#endif /* WL_POINTER_AXIS_ENUM */
++
++#ifndef WL_POINTER_AXIS_SOURCE_ENUM
++#define WL_POINTER_AXIS_SOURCE_ENUM
++/**
++ * @ingroup iface_wl_pointer
++ * axis source types
++ *
++ * Describes the source types for axis events. This indicates to the
++ * client how an axis event was physically generated; a client may
++ * adjust the user interface accordingly. For example, scroll events
++ * from a "finger" source may be in a smooth coordinate space with
++ * kinetic scrolling whereas a "wheel" source may be in discrete steps
++ * of a number of lines.
++ */
++enum wl_pointer_axis_source {
++ /**
++ * a physical wheel rotation
++ */
++ WL_POINTER_AXIS_SOURCE_WHEEL = 0,
++ /**
++ * finger on a touch surface
++ */
++ WL_POINTER_AXIS_SOURCE_FINGER = 1,
++ /**
++ * continuous coordinate space
++ *
++ * A device generating events in a continuous coordinate space,
++ * but using something other than a finger. One example for this
++ * source is button-based scrolling where the vertical motion of a
++ * device is converted to scroll events while a button is held
++ * down.
++ */
++ WL_POINTER_AXIS_SOURCE_CONTINUOUS = 2,
++ /**
++ * a physical wheel tilt
++ *
++ * Indicates that the actual device is a wheel but the scroll
++ * event is not caused by a rotation but a (usually sideways) tilt
++ * of the wheel.
++ * @since 6
++ */
++ WL_POINTER_AXIS_SOURCE_WHEEL_TILT = 3,
++};
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION 6
++#endif /* WL_POINTER_AXIS_SOURCE_ENUM */
++
++/**
++ * @ingroup iface_wl_pointer
++ * @struct wl_pointer_interface
++ */
++struct wl_pointer_interface {
++ /**
++ * set the pointer surface
++ *
++ * Set the pointer surface, i.e., the surface that contains the
++ * pointer image (cursor). This request gives the surface the role
++ * of a cursor. If the surface already has another role, it raises
++ * a protocol error.
++ *
++ * The cursor actually changes only if the pointer focus for this
++ * device is one of the requesting client's surfaces or the surface
++ * parameter is the current pointer surface. If there was a
++ * previous surface set with this request it is replaced. If
++ * surface is NULL, the pointer image is hidden.
++ *
++ * The parameters hotspot_x and hotspot_y define the position of
++ * the pointer surface relative to the pointer location. Its
++ * top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
++ * where (x, y) are the coordinates of the pointer location, in
++ * surface-local coordinates.
++ *
++ * On surface.attach requests to the pointer surface, hotspot_x and
++ * hotspot_y are decremented by the x and y parameters passed to
++ * the request. Attach must be confirmed by wl_surface.commit as
++ * usual.
++ *
++ * The hotspot can also be updated by passing the currently set
++ * pointer surface to this request with new values for hotspot_x
++ * and hotspot_y.
++ *
++ * The current and pending input regions of the wl_surface are
++ * cleared, and wl_surface.set_input_region is ignored until the
++ * wl_surface is no longer used as the cursor. When the use as a
++ * cursor ends, the current and pending input regions become
++ * undefined, and the wl_surface is unmapped.
++ * @param serial serial number of the enter event
++ * @param surface pointer surface
++ * @param hotspot_x surface-local x coordinate
++ * @param hotspot_y surface-local y coordinate
++ */
++ void (*set_cursor)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t serial,
++ struct wl_resource *surface,
++ int32_t hotspot_x,
++ int32_t hotspot_y);
++ /**
++ * release the pointer object
++ *
++ * Using this request a client can tell the server that it is not
++ * going to use the pointer object anymore.
++ *
++ * This request destroys the pointer proxy object, so clients must
++ * not call wl_pointer_destroy() after using this request.
++ * @since 3
++ */
++ void (*release)(struct wl_client *client,
++ struct wl_resource *resource);
++};
++
++#define WL_POINTER_ENTER 0
++#define WL_POINTER_LEAVE 1
++#define WL_POINTER_MOTION 2
++#define WL_POINTER_BUTTON 3
++#define WL_POINTER_AXIS 4
++#define WL_POINTER_FRAME 5
++#define WL_POINTER_AXIS_SOURCE 6
++#define WL_POINTER_AXIS_STOP 7
++#define WL_POINTER_AXIS_DISCRETE 8
++
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_LEAVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_MOTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_BUTTON_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_FRAME_SINCE_VERSION 5
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_SOURCE_SINCE_VERSION 5
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_STOP_SINCE_VERSION 5
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_DISCRETE_SINCE_VERSION 5
++
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_SET_CURSOR_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_RELEASE_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an enter event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the enter event
++ * @param surface surface entered by the pointer
++ * @param surface_x surface-local x coordinate
++ * @param surface_y surface-local y coordinate
++ */
++static inline void
++wl_pointer_send_enter(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface, wl_fixed_t surface_x, wl_fixed_t surface_y)
++{
++ wl_resource_post_event(resource_, WL_POINTER_ENTER, serial, surface, surface_x, surface_y);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an leave event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the leave event
++ * @param surface surface left by the pointer
++ */
++static inline void
++wl_pointer_send_leave(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface)
++{
++ wl_resource_post_event(resource_, WL_POINTER_LEAVE, serial, surface);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an motion event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param time timestamp with millisecond granularity
++ * @param surface_x surface-local x coordinate
++ * @param surface_y surface-local y coordinate
++ */
++static inline void
++wl_pointer_send_motion(struct wl_resource *resource_, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
++{
++ wl_resource_post_event(resource_, WL_POINTER_MOTION, time, surface_x, surface_y);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an button event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the button event
++ * @param time timestamp with millisecond granularity
++ * @param button button that produced the event
++ * @param state physical state of the button
++ */
++static inline void
++wl_pointer_send_button(struct wl_resource *resource_, uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
++{
++ wl_resource_post_event(resource_, WL_POINTER_BUTTON, serial, time, button, state);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an axis event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param time timestamp with millisecond granularity
++ * @param axis axis type
++ * @param value length of vector in surface-local coordinate space
++ */
++static inline void
++wl_pointer_send_axis(struct wl_resource *resource_, uint32_t time, uint32_t axis, wl_fixed_t value)
++{
++ wl_resource_post_event(resource_, WL_POINTER_AXIS, time, axis, value);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an frame event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_pointer_send_frame(struct wl_resource *resource_)
++{
++ wl_resource_post_event(resource_, WL_POINTER_FRAME);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an axis_source event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param axis_source source of the axis event
++ */
++static inline void
++wl_pointer_send_axis_source(struct wl_resource *resource_, uint32_t axis_source)
++{
++ wl_resource_post_event(resource_, WL_POINTER_AXIS_SOURCE, axis_source);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an axis_stop event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param time timestamp with millisecond granularity
++ * @param axis the axis stopped with this event
++ */
++static inline void
++wl_pointer_send_axis_stop(struct wl_resource *resource_, uint32_t time, uint32_t axis)
++{
++ wl_resource_post_event(resource_, WL_POINTER_AXIS_STOP, time, axis);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an axis_discrete event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param axis axis type
++ * @param discrete number of steps
++ */
++static inline void
++wl_pointer_send_axis_discrete(struct wl_resource *resource_, uint32_t axis, int32_t discrete)
++{
++ wl_resource_post_event(resource_, WL_POINTER_AXIS_DISCRETE, axis, discrete);
++}
++
++#ifndef WL_KEYBOARD_KEYMAP_FORMAT_ENUM
++#define WL_KEYBOARD_KEYMAP_FORMAT_ENUM
++/**
++ * @ingroup iface_wl_keyboard
++ * keyboard mapping format
++ *
++ * This specifies the format of the keymap provided to the
++ * client with the wl_keyboard.keymap event.
++ */
++enum wl_keyboard_keymap_format {
++ /**
++ * no keymap; client must understand how to interpret the raw keycode
++ */
++ WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP = 0,
++ /**
++ * libxkbcommon compatible; to determine the xkb keycode, clients must add 8 to the key event keycode
++ */
++ WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 = 1,
++};
++#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM */
++
++#ifndef WL_KEYBOARD_KEY_STATE_ENUM
++#define WL_KEYBOARD_KEY_STATE_ENUM
++/**
++ * @ingroup iface_wl_keyboard
++ * physical key state
++ *
++ * Describes the physical state of a key that produced the key event.
++ */
++enum wl_keyboard_key_state {
++ /**
++ * key is not pressed
++ */
++ WL_KEYBOARD_KEY_STATE_RELEASED = 0,
++ /**
++ * key is pressed
++ */
++ WL_KEYBOARD_KEY_STATE_PRESSED = 1,
++};
++#endif /* WL_KEYBOARD_KEY_STATE_ENUM */
++
++/**
++ * @ingroup iface_wl_keyboard
++ * @struct wl_keyboard_interface
++ */
++struct wl_keyboard_interface {
++ /**
++ * release the keyboard object
++ *
++ *
++ * @since 3
++ */
++ void (*release)(struct wl_client *client,
++ struct wl_resource *resource);
++};
++
++#define WL_KEYBOARD_KEYMAP 0
++#define WL_KEYBOARD_ENTER 1
++#define WL_KEYBOARD_LEAVE 2
++#define WL_KEYBOARD_KEY 3
++#define WL_KEYBOARD_MODIFIERS 4
++#define WL_KEYBOARD_REPEAT_INFO 5
++
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_KEYMAP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_LEAVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_KEY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_MODIFIERS_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION 4
++
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_RELEASE_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_keyboard
++ * Sends an keymap event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param format keymap format
++ * @param fd keymap file descriptor
++ * @param size keymap size, in bytes
++ */
++static inline void
++wl_keyboard_send_keymap(struct wl_resource *resource_, uint32_t format, int32_t fd, uint32_t size)
++{
++ wl_resource_post_event(resource_, WL_KEYBOARD_KEYMAP, format, fd, size);
++}
++
++/**
++ * @ingroup iface_wl_keyboard
++ * Sends an enter event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the enter event
++ * @param surface surface gaining keyboard focus
++ * @param keys the currently pressed keys
++ */
++static inline void
++wl_keyboard_send_enter(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface, struct wl_array *keys)
++{
++ wl_resource_post_event(resource_, WL_KEYBOARD_ENTER, serial, surface, keys);
++}
++
++/**
++ * @ingroup iface_wl_keyboard
++ * Sends an leave event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the leave event
++ * @param surface surface that lost keyboard focus
++ */
++static inline void
++wl_keyboard_send_leave(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface)
++{
++ wl_resource_post_event(resource_, WL_KEYBOARD_LEAVE, serial, surface);
++}
++
++/**
++ * @ingroup iface_wl_keyboard
++ * Sends an key event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the key event
++ * @param time timestamp with millisecond granularity
++ * @param key key that produced the event
++ * @param state physical state of the key
++ */
++static inline void
++wl_keyboard_send_key(struct wl_resource *resource_, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
++{
++ wl_resource_post_event(resource_, WL_KEYBOARD_KEY, serial, time, key, state);
++}
++
++/**
++ * @ingroup iface_wl_keyboard
++ * Sends an modifiers event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the modifiers event
++ * @param mods_depressed depressed modifiers
++ * @param mods_latched latched modifiers
++ * @param mods_locked locked modifiers
++ * @param group keyboard layout
++ */
++static inline void
++wl_keyboard_send_modifiers(struct wl_resource *resource_, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
++{
++ wl_resource_post_event(resource_, WL_KEYBOARD_MODIFIERS, serial, mods_depressed, mods_latched, mods_locked, group);
++}
++
++/**
++ * @ingroup iface_wl_keyboard
++ * Sends an repeat_info event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param rate the rate of repeating keys in characters per second
++ * @param delay delay in milliseconds since key down until repeating starts
++ */
++static inline void
++wl_keyboard_send_repeat_info(struct wl_resource *resource_, int32_t rate, int32_t delay)
++{
++ wl_resource_post_event(resource_, WL_KEYBOARD_REPEAT_INFO, rate, delay);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * @struct wl_touch_interface
++ */
++struct wl_touch_interface {
++ /**
++ * release the touch object
++ *
++ *
++ * @since 3
++ */
++ void (*release)(struct wl_client *client,
++ struct wl_resource *resource);
++};
++
++#define WL_TOUCH_DOWN 0
++#define WL_TOUCH_UP 1
++#define WL_TOUCH_MOTION 2
++#define WL_TOUCH_FRAME 3
++#define WL_TOUCH_CANCEL 4
++#define WL_TOUCH_SHAPE 5
++#define WL_TOUCH_ORIENTATION 6
++
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_DOWN_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_UP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_MOTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_FRAME_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_CANCEL_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_SHAPE_SINCE_VERSION 6
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_ORIENTATION_SINCE_VERSION 6
++
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_RELEASE_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_touch
++ * Sends an down event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the touch down event
++ * @param time timestamp with millisecond granularity
++ * @param surface surface touched
++ * @param id the unique ID of this touch point
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ */
++static inline void
++wl_touch_send_down(struct wl_resource *resource_, uint32_t serial, uint32_t time, struct wl_resource *surface, int32_t id, wl_fixed_t x, wl_fixed_t y)
++{
++ wl_resource_post_event(resource_, WL_TOUCH_DOWN, serial, time, surface, id, x, y);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * Sends an up event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the touch up event
++ * @param time timestamp with millisecond granularity
++ * @param id the unique ID of this touch point
++ */
++static inline void
++wl_touch_send_up(struct wl_resource *resource_, uint32_t serial, uint32_t time, int32_t id)
++{
++ wl_resource_post_event(resource_, WL_TOUCH_UP, serial, time, id);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * Sends an motion event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param time timestamp with millisecond granularity
++ * @param id the unique ID of this touch point
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ */
++static inline void
++wl_touch_send_motion(struct wl_resource *resource_, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
++{
++ wl_resource_post_event(resource_, WL_TOUCH_MOTION, time, id, x, y);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * Sends an frame event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_touch_send_frame(struct wl_resource *resource_)
++{
++ wl_resource_post_event(resource_, WL_TOUCH_FRAME);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * Sends an cancel event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_touch_send_cancel(struct wl_resource *resource_)
++{
++ wl_resource_post_event(resource_, WL_TOUCH_CANCEL);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * Sends an shape event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param id the unique ID of this touch point
++ * @param major length of the major axis in surface-local coordinates
++ * @param minor length of the minor axis in surface-local coordinates
++ */
++static inline void
++wl_touch_send_shape(struct wl_resource *resource_, int32_t id, wl_fixed_t major, wl_fixed_t minor)
++{
++ wl_resource_post_event(resource_, WL_TOUCH_SHAPE, id, major, minor);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * Sends an orientation event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param id the unique ID of this touch point
++ * @param orientation angle between major axis and positive surface y-axis in degrees
++ */
++static inline void
++wl_touch_send_orientation(struct wl_resource *resource_, int32_t id, wl_fixed_t orientation)
++{
++ wl_resource_post_event(resource_, WL_TOUCH_ORIENTATION, id, orientation);
++}
++
++#ifndef WL_OUTPUT_SUBPIXEL_ENUM
++#define WL_OUTPUT_SUBPIXEL_ENUM
++/**
++ * @ingroup iface_wl_output
++ * subpixel geometry information
++ *
++ * This enumeration describes how the physical
++ * pixels on an output are laid out.
++ */
++enum wl_output_subpixel {
++ /**
++ * unknown geometry
++ */
++ WL_OUTPUT_SUBPIXEL_UNKNOWN = 0,
++ /**
++ * no geometry
++ */
++ WL_OUTPUT_SUBPIXEL_NONE = 1,
++ /**
++ * horizontal RGB
++ */
++ WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB = 2,
++ /**
++ * horizontal BGR
++ */
++ WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR = 3,
++ /**
++ * vertical RGB
++ */
++ WL_OUTPUT_SUBPIXEL_VERTICAL_RGB = 4,
++ /**
++ * vertical BGR
++ */
++ WL_OUTPUT_SUBPIXEL_VERTICAL_BGR = 5,
++};
++#endif /* WL_OUTPUT_SUBPIXEL_ENUM */
++
++#ifndef WL_OUTPUT_TRANSFORM_ENUM
++#define WL_OUTPUT_TRANSFORM_ENUM
++/**
++ * @ingroup iface_wl_output
++ * transform from framebuffer to output
++ *
++ * This describes the transform that a compositor will apply to a
++ * surface to compensate for the rotation or mirroring of an
++ * output device.
++ *
++ * The flipped values correspond to an initial flip around a
++ * vertical axis followed by rotation.
++ *
++ * The purpose is mainly to allow clients to render accordingly and
++ * tell the compositor, so that for fullscreen surfaces, the
++ * compositor will still be able to scan out directly from client
++ * surfaces.
++ */
++enum wl_output_transform {
++ /**
++ * no transform
++ */
++ WL_OUTPUT_TRANSFORM_NORMAL = 0,
++ /**
++ * 90 degrees counter-clockwise
++ */
++ WL_OUTPUT_TRANSFORM_90 = 1,
++ /**
++ * 180 degrees counter-clockwise
++ */
++ WL_OUTPUT_TRANSFORM_180 = 2,
++ /**
++ * 270 degrees counter-clockwise
++ */
++ WL_OUTPUT_TRANSFORM_270 = 3,
++ /**
++ * 180 degree flip around a vertical axis
++ */
++ WL_OUTPUT_TRANSFORM_FLIPPED = 4,
++ /**
++ * flip and rotate 90 degrees counter-clockwise
++ */
++ WL_OUTPUT_TRANSFORM_FLIPPED_90 = 5,
++ /**
++ * flip and rotate 180 degrees counter-clockwise
++ */
++ WL_OUTPUT_TRANSFORM_FLIPPED_180 = 6,
++ /**
++ * flip and rotate 270 degrees counter-clockwise
++ */
++ WL_OUTPUT_TRANSFORM_FLIPPED_270 = 7,
++};
++#endif /* WL_OUTPUT_TRANSFORM_ENUM */
++
++#ifndef WL_OUTPUT_MODE_ENUM
++#define WL_OUTPUT_MODE_ENUM
++/**
++ * @ingroup iface_wl_output
++ * mode information
++ *
++ * These flags describe properties of an output mode.
++ * They are used in the flags bitfield of the mode event.
++ */
++enum wl_output_mode {
++ /**
++ * indicates this is the current mode
++ */
++ WL_OUTPUT_MODE_CURRENT = 0x1,
++ /**
++ * indicates this is the preferred mode
++ */
++ WL_OUTPUT_MODE_PREFERRED = 0x2,
++};
++#endif /* WL_OUTPUT_MODE_ENUM */
++
++/**
++ * @ingroup iface_wl_output
++ * @struct wl_output_interface
++ */
++struct wl_output_interface {
++ /**
++ * release the output object
++ *
++ * Using this request a client can tell the server that it is not
++ * going to use the output object anymore.
++ * @since 3
++ */
++ void (*release)(struct wl_client *client,
++ struct wl_resource *resource);
++};
++
++#define WL_OUTPUT_GEOMETRY 0
++#define WL_OUTPUT_MODE 1
++#define WL_OUTPUT_DONE 2
++#define WL_OUTPUT_SCALE 3
++
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_GEOMETRY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_MODE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_DONE_SINCE_VERSION 2
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_SCALE_SINCE_VERSION 2
++
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_RELEASE_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_output
++ * Sends an geometry event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param x x position within the global compositor space
++ * @param y y position within the global compositor space
++ * @param physical_width width in millimeters of the output
++ * @param physical_height height in millimeters of the output
++ * @param subpixel subpixel orientation of the output
++ * @param make textual description of the manufacturer
++ * @param model textual description of the model
++ * @param transform transform that maps framebuffer to output
++ */
++static inline void
++wl_output_send_geometry(struct wl_resource *resource_, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char *make, const char *model, int32_t transform)
++{
++ wl_resource_post_event(resource_, WL_OUTPUT_GEOMETRY, x, y, physical_width, physical_height, subpixel, make, model, transform);
++}
++
++/**
++ * @ingroup iface_wl_output
++ * Sends an mode event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param flags bitfield of mode flags
++ * @param width width of the mode in hardware units
++ * @param height height of the mode in hardware units
++ * @param refresh vertical refresh rate in mHz
++ */
++static inline void
++wl_output_send_mode(struct wl_resource *resource_, uint32_t flags, int32_t width, int32_t height, int32_t refresh)
++{
++ wl_resource_post_event(resource_, WL_OUTPUT_MODE, flags, width, height, refresh);
++}
++
++/**
++ * @ingroup iface_wl_output
++ * Sends an done event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_output_send_done(struct wl_resource *resource_)
++{
++ wl_resource_post_event(resource_, WL_OUTPUT_DONE);
++}
++
++/**
++ * @ingroup iface_wl_output
++ * Sends an scale event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param factor scaling factor of output
++ */
++static inline void
++wl_output_send_scale(struct wl_resource *resource_, int32_t factor)
++{
++ wl_resource_post_event(resource_, WL_OUTPUT_SCALE, factor);
++}
++
++/**
++ * @ingroup iface_wl_region
++ * @struct wl_region_interface
++ */
++struct wl_region_interface {
++ /**
++ * destroy region
++ *
++ * Destroy the region. This will invalidate the object ID.
++ */
++ void (*destroy)(struct wl_client *client,
++ struct wl_resource *resource);
++ /**
++ * add rectangle to region
++ *
++ * Add the specified rectangle to the region.
++ * @param x region-local x coordinate
++ * @param y region-local y coordinate
++ * @param width rectangle width
++ * @param height rectangle height
++ */
++ void (*add)(struct wl_client *client,
++ struct wl_resource *resource,
++ int32_t x,
++ int32_t y,
++ int32_t width,
++ int32_t height);
++ /**
++ * subtract rectangle from region
++ *
++ * Subtract the specified rectangle from the region.
++ * @param x region-local x coordinate
++ * @param y region-local y coordinate
++ * @param width rectangle width
++ * @param height rectangle height
++ */
++ void (*subtract)(struct wl_client *client,
++ struct wl_resource *resource,
++ int32_t x,
++ int32_t y,
++ int32_t width,
++ int32_t height);
++};
++
++
++/**
++ * @ingroup iface_wl_region
++ */
++#define WL_REGION_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_region
++ */
++#define WL_REGION_ADD_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_region
++ */
++#define WL_REGION_SUBTRACT_SINCE_VERSION 1
++
++#ifndef WL_SUBCOMPOSITOR_ERROR_ENUM
++#define WL_SUBCOMPOSITOR_ERROR_ENUM
++enum wl_subcompositor_error {
++ /**
++ * the to-be sub-surface is invalid
++ */
++ WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE = 0,
++};
++#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_subcompositor
++ * @struct wl_subcompositor_interface
++ */
++struct wl_subcompositor_interface {
++ /**
++ * unbind from the subcompositor interface
++ *
++ * Informs the server that the client will not be using this
++ * protocol object anymore. This does not affect any other objects,
++ * wl_subsurface objects included.
++ */
++ void (*destroy)(struct wl_client *client,
++ struct wl_resource *resource);
++ /**
++ * give a surface the role sub-surface
++ *
++ * Create a sub-surface interface for the given surface, and
++ * associate it with the given parent surface. This turns a plain
++ * wl_surface into a sub-surface.
++ *
++ * The to-be sub-surface must not already have another role, and it
++ * must not have an existing wl_subsurface object. Otherwise a
++ * protocol error is raised.
++ * @param id the new sub-surface object ID
++ * @param surface the surface to be turned into a sub-surface
++ * @param parent the parent surface
++ */
++ void (*get_subsurface)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t id,
++ struct wl_resource *surface,
++ struct wl_resource *parent);
++};
++
++
++/**
++ * @ingroup iface_wl_subcompositor
++ */
++#define WL_SUBCOMPOSITOR_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subcompositor
++ */
++#define WL_SUBCOMPOSITOR_GET_SUBSURFACE_SINCE_VERSION 1
++
++#ifndef WL_SUBSURFACE_ERROR_ENUM
++#define WL_SUBSURFACE_ERROR_ENUM
++enum wl_subsurface_error {
++ /**
++ * wl_surface is not a sibling or the parent
++ */
++ WL_SUBSURFACE_ERROR_BAD_SURFACE = 0,
++};
++#endif /* WL_SUBSURFACE_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_subsurface
++ * @struct wl_subsurface_interface
++ */
++struct wl_subsurface_interface {
++ /**
++ * remove sub-surface interface
++ *
++ * The sub-surface interface is removed from the wl_surface
++ * object that was turned into a sub-surface with a
++ * wl_subcompositor.get_subsurface request. The wl_surface's
++ * association to the parent is deleted, and the wl_surface loses
++ * its role as a sub-surface. The wl_surface is unmapped.
++ */
++ void (*destroy)(struct wl_client *client,
++ struct wl_resource *resource);
++ /**
++ * reposition the sub-surface
++ *
++ * This schedules a sub-surface position change. The sub-surface
++ * will be moved so that its origin (top left corner pixel) will be
++ * at the location x, y of the parent surface coordinate system.
++ * The coordinates are not restricted to the parent surface area.
++ * Negative values are allowed.
++ *
++ * The scheduled coordinates will take effect whenever the state of
++ * the parent surface is applied. When this happens depends on
++ * whether the parent surface is in synchronized mode or not. See
++ * wl_subsurface.set_sync and wl_subsurface.set_desync for details.
++ *
++ * If more than one set_position request is invoked by the client
++ * before the commit of the parent surface, the position of a new
++ * request always replaces the scheduled position from any previous
++ * request.
++ *
++ * The initial position is 0, 0.
++ * @param x x coordinate in the parent surface
++ * @param y y coordinate in the parent surface
++ */
++ void (*set_position)(struct wl_client *client,
++ struct wl_resource *resource,
++ int32_t x,
++ int32_t y);
++ /**
++ * restack the sub-surface
++ *
++ * This sub-surface is taken from the stack, and put back just
++ * above the reference surface, changing the z-order of the
++ * sub-surfaces. The reference surface must be one of the sibling
++ * surfaces, or the parent surface. Using any other surface,
++ * including this sub-surface, will cause a protocol error.
++ *
++ * The z-order is double-buffered. Requests are handled in order
++ * and applied immediately to a pending state. The final pending
++ * state is copied to the active state the next time the state of
++ * the parent surface is applied. When this happens depends on
++ * whether the parent surface is in synchronized mode or not. See
++ * wl_subsurface.set_sync and wl_subsurface.set_desync for details.
++ *
++ * A new sub-surface is initially added as the top-most in the
++ * stack of its siblings and parent.
++ * @param sibling the reference surface
++ */
++ void (*place_above)(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *sibling);
++ /**
++ * restack the sub-surface
++ *
++ * The sub-surface is placed just below the reference surface.
++ * See wl_subsurface.place_above.
++ * @param sibling the reference surface
++ */
++ void (*place_below)(struct wl_client *client,
++ struct wl_resource *resource,
++ struct wl_resource *sibling);
++ /**
++ * set sub-surface to synchronized mode
++ *
++ * Change the commit behaviour of the sub-surface to synchronized
++ * mode, also described as the parent dependent mode.
++ *
++ * In synchronized mode, wl_surface.commit on a sub-surface will
++ * accumulate the committed state in a cache, but the state will
++ * not be applied and hence will not change the compositor output.
++ * The cached state is applied to the sub-surface immediately after
++ * the parent surface's state is applied. This ensures atomic
++ * updates of the parent and all its synchronized sub-surfaces.
++ * Applying the cached state will invalidate the cache, so further
++ * parent surface commits do not (re-)apply old state.
++ *
++ * See wl_subsurface for the recursive effect of this mode.
++ */
++ void (*set_sync)(struct wl_client *client,
++ struct wl_resource *resource);
++ /**
++ * set sub-surface to desynchronized mode
++ *
++ * Change the commit behaviour of the sub-surface to
++ * desynchronized mode, also described as independent or freely
++ * running mode.
++ *
++ * In desynchronized mode, wl_surface.commit on a sub-surface will
++ * apply the pending state directly, without caching, as happens
++ * normally with a wl_surface. Calling wl_surface.commit on the
++ * parent surface has no effect on the sub-surface's wl_surface
++ * state. This mode allows a sub-surface to be updated on its own.
++ *
++ * If cached state exists when wl_surface.commit is called in
++ * desynchronized mode, the pending state is added to the cached
++ * state, and applied as a whole. This invalidates the cache.
++ *
++ * Note: even if a sub-surface is set to desynchronized, a parent
++ * sub-surface may override it to behave as synchronized. For
++ * details, see wl_subsurface.
++ *
++ * If a surface's parent surface behaves as desynchronized, then
++ * the cached state is applied on set_desync.
++ */
++ void (*set_desync)(struct wl_client *client,
++ struct wl_resource *resource);
++};
++
++
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_SET_POSITION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_PLACE_ABOVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_PLACE_BELOW_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_SET_SYNC_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_SET_DESYNC_SINCE_VERSION 1
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="wayland">
++
++ <copyright>
++ Copyright © 2008-2011 Kristian Høgsberg
++ Copyright © 2010-2011 Intel Corporation
++ Copyright © 2012-2013 Collabora, Ltd.
++
++ Permission is hereby granted, free of charge, to any person
++ obtaining a copy of this software and associated documentation files
++ (the "Software"), to deal in the Software without restriction,
++ including without limitation the rights to use, copy, modify, merge,
++ publish, distribute, sublicense, and/or sell copies of the Software,
++ and to permit persons to whom the Software is furnished to do so,
++ subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the
++ next paragraph) shall be included in all copies or substantial
++ portions of the Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ SOFTWARE.
++ </copyright>
++
++ <interface name="wl_display" version="1">
++ <description summary="core global object">
++ The core global object. This is a special singleton object. It
++ is used for internal Wayland protocol features.
++ </description>
++
++ <request name="sync">
++ <description summary="asynchronous roundtrip">
++ The sync request asks the server to emit the 'done' event
++ on the returned wl_callback object. Since requests are
++ handled in-order and events are delivered in-order, this can
++ be used as a barrier to ensure all previous requests and the
++ resulting events have been handled.
++
++ The object returned by this request will be destroyed by the
++ compositor after the callback is fired and as such the client must not
++ attempt to use it after that point.
++
++ The callback_data passed in the callback is the event serial.
++ </description>
++ <arg name="callback" type="new_id" interface="wl_callback"
++ summary="callback object for the sync request"/>
++ </request>
++
++ <request name="get_registry">
++ <description summary="get global registry object">
++ This request creates a registry object that allows the client
++ to list and bind the global objects available from the
++ compositor.
++ </description>
++ <arg name="registry" type="new_id" interface="wl_registry"
++ summary="global registry object"/>
++ </request>
++
++ <event name="error">
++ <description summary="fatal error event">
++ The error event is sent out when a fatal (non-recoverable)
++ error has occurred. The object_id argument is the object
++ where the error occurred, most often in response to a request
++ to that object. The code identifies the error and is defined
++ by the object interface. As such, each interface defines its
++ own set of error codes. The message is a brief description
++ of the error, for (debugging) convenience.
++ </description>
++ <arg name="object_id" type="object" summary="object where the error occurred"/>
++ <arg name="code" type="uint" summary="error code"/>
++ <arg name="message" type="string" summary="error description"/>
++ </event>
++
++ <enum name="error">
++ <description summary="global error values">
++ These errors are global and can be emitted in response to any
++ server request.
++ </description>
++ <entry name="invalid_object" value="0"
++ summary="server couldn't find object"/>
++ <entry name="invalid_method" value="1"
++ summary="method doesn't exist on the specified interface"/>
++ <entry name="no_memory" value="2"
++ summary="server is out of memory"/>
++ </enum>
++
++ <event name="delete_id">
++ <description summary="acknowledge object ID deletion">
++ This event is used internally by the object ID management
++ logic. When a client deletes an object, the server will send
++ this event to acknowledge that it has seen the delete request.
++ When the client receives this event, it will know that it can
++ safely reuse the object ID.
++ </description>
++ <arg name="id" type="uint" summary="deleted object ID"/>
++ </event>
++ </interface>
++
++ <interface name="wl_registry" version="1">
++ <description summary="global registry object">
++ The singleton global registry object. The server has a number of
++ global objects that are available to all clients. These objects
++ typically represent an actual object in the server (for example,
++ an input device) or they are singleton objects that provide
++ extension functionality.
++
++ When a client creates a registry object, the registry object
++ will emit a global event for each global currently in the
++ registry. Globals come and go as a result of device or
++ monitor hotplugs, reconfiguration or other events, and the
++ registry will send out global and global_remove events to
++ keep the client up to date with the changes. To mark the end
++ of the initial burst of events, the client can use the
++ wl_display.sync request immediately after calling
++ wl_display.get_registry.
++
++ A client can bind to a global object by using the bind
++ request. This creates a client-side handle that lets the object
++ emit events to the client and lets the client invoke requests on
++ the object.
++ </description>
++
++ <request name="bind">
++ <description summary="bind an object to the display">
++ Binds a new, client-created object to the server using the
++ specified name as the identifier.
++ </description>
++ <arg name="name" type="uint" summary="unique numeric name of the object"/>
++ <arg name="id" type="new_id" summary="bounded object"/>
++ </request>
++
++ <event name="global">
++ <description summary="announce global object">
++ Notify the client of global objects.
++
++ The event notifies the client that a global object with
++ the given name is now available, and it implements the
++ given version of the given interface.
++ </description>
++ <arg name="name" type="uint" summary="numeric name of the global object"/>
++ <arg name="interface" type="string" summary="interface implemented by the object"/>
++ <arg name="version" type="uint" summary="interface version"/>
++ </event>
++
++ <event name="global_remove">
++ <description summary="announce removal of global object">
++ Notify the client of removed global objects.
++
++ This event notifies the client that the global identified
++ by name is no longer available. If the client bound to
++ the global using the bind request, the client should now
++ destroy that object.
++
++ The object remains valid and requests to the object will be
++ ignored until the client destroys it, to avoid races between
++ the global going away and a client sending a request to it.
++ </description>
++ <arg name="name" type="uint" summary="numeric name of the global object"/>
++ </event>
++ </interface>
++
++ <interface name="wl_callback" version="1">
++ <description summary="callback object">
++ Clients can handle the 'done' event to get notified when
++ the related request is done.
++ </description>
++
++ <event name="done">
++ <description summary="done event">
++ Notify the client when the related request is done.
++ </description>
++ <arg name="callback_data" type="uint" summary="request-specific data for the callback"/>
++ </event>
++ </interface>
++
++ <interface name="wl_compositor" version="4">
++ <description summary="the compositor singleton">
++ A compositor. This object is a singleton global. The
++ compositor is in charge of combining the contents of multiple
++ surfaces into one displayable output.
++ </description>
++
++ <request name="create_surface">
++ <description summary="create new surface">
++ Ask the compositor to create a new surface.
++ </description>
++ <arg name="id" type="new_id" interface="wl_surface" summary="the new surface"/>
++ </request>
++
++ <request name="create_region">
++ <description summary="create new region">
++ Ask the compositor to create a new region.
++ </description>
++ <arg name="id" type="new_id" interface="wl_region" summary="the new region"/>
++ </request>
++ </interface>
++
++ <interface name="wl_shm_pool" version="1">
++ <description summary="a shared memory pool">
++ The wl_shm_pool object encapsulates a piece of memory shared
++ between the compositor and client. Through the wl_shm_pool
++ object, the client can allocate shared memory wl_buffer objects.
++ All objects created through the same pool share the same
++ underlying mapped memory. Reusing the mapped memory avoids the
++ setup/teardown overhead and is useful when interactively resizing
++ a surface or for many small buffers.
++ </description>
++
++ <request name="create_buffer">
++ <description summary="create a buffer from the pool">
++ Create a wl_buffer object from the pool.
++
++ The buffer is created offset bytes into the pool and has
++ width and height as specified. The stride argument specifies
++ the number of bytes from the beginning of one row to the beginning
++ of the next. The format is the pixel format of the buffer and
++ must be one of those advertised through the wl_shm.format event.
++
++ A buffer will keep a reference to the pool it was created from
++ so it is valid to destroy the pool immediately after creating
++ a buffer from it.
++ </description>
++ <arg name="id" type="new_id" interface="wl_buffer" summary="buffer to create"/>
++ <arg name="offset" type="int" summary="buffer byte offset within the pool"/>
++ <arg name="width" type="int" summary="buffer width, in pixels"/>
++ <arg name="height" type="int" summary="buffer height, in pixels"/>
++ <arg name="stride" type="int" summary="number of bytes from the beginning of one row to the beginning of the next row"/>
++ <arg name="format" type="uint" enum="wl_shm.format" summary="buffer pixel format"/>
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the pool">
++ Destroy the shared memory pool.
++
++ The mmapped memory will be released when all
++ buffers that have been created from this pool
++ are gone.
++ </description>
++ </request>
++
++ <request name="resize">
++ <description summary="change the size of the pool mapping">
++ This request will cause the server to remap the backing memory
++ for the pool from the file descriptor passed when the pool was
++ created, but using the new size. This request can only be
++ used to make the pool bigger.
++ </description>
++ <arg name="size" type="int" summary="new size of the pool, in bytes"/>
++ </request>
++ </interface>
++
++ <interface name="wl_shm" version="1">
++ <description summary="shared memory support">
++ A singleton global object that provides support for shared
++ memory.
++
++ Clients can create wl_shm_pool objects using the create_pool
++ request.
++
++ At connection setup time, the wl_shm object emits one or more
++ format events to inform clients about the valid pixel formats
++ that can be used for buffers.
++ </description>
++
++ <enum name="error">
++ <description summary="wl_shm error values">
++ These errors can be emitted in response to wl_shm requests.
++ </description>
++ <entry name="invalid_format" value="0" summary="buffer format is not known"/>
++ <entry name="invalid_stride" value="1" summary="invalid size or stride during pool or buffer creation"/>
++ <entry name="invalid_fd" value="2" summary="mmapping the file descriptor failed"/>
++ </enum>
++
++ <enum name="format">
++ <description summary="pixel formats">
++ This describes the memory layout of an individual pixel.
++
++ All renderers should support argb8888 and xrgb8888 but any other
++ formats are optional and may not be supported by the particular
++ renderer in use.
++
++ The drm format codes match the macros defined in drm_fourcc.h.
++ The formats actually supported by the compositor will be
++ reported by the format event.
++ </description>
++ <entry name="argb8888" value="0" summary="32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian"/>
++ <entry name="xrgb8888" value="1" summary="32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian"/>
++ <entry name="c8" value="0x20203843" summary="8-bit color index format, [7:0] C"/>
++ <entry name="rgb332" value="0x38424752" summary="8-bit RGB format, [7:0] R:G:B 3:3:2"/>
++ <entry name="bgr233" value="0x38524742" summary="8-bit BGR format, [7:0] B:G:R 2:3:3"/>
++ <entry name="xrgb4444" value="0x32315258" summary="16-bit xRGB format, [15:0] x:R:G:B 4:4:4:4 little endian"/>
++ <entry name="xbgr4444" value="0x32314258" summary="16-bit xBGR format, [15:0] x:B:G:R 4:4:4:4 little endian"/>
++ <entry name="rgbx4444" value="0x32315852" summary="16-bit RGBx format, [15:0] R:G:B:x 4:4:4:4 little endian"/>
++ <entry name="bgrx4444" value="0x32315842" summary="16-bit BGRx format, [15:0] B:G:R:x 4:4:4:4 little endian"/>
++ <entry name="argb4444" value="0x32315241" summary="16-bit ARGB format, [15:0] A:R:G:B 4:4:4:4 little endian"/>
++ <entry name="abgr4444" value="0x32314241" summary="16-bit ABGR format, [15:0] A:B:G:R 4:4:4:4 little endian"/>
++ <entry name="rgba4444" value="0x32314152" summary="16-bit RBGA format, [15:0] R:G:B:A 4:4:4:4 little endian"/>
++ <entry name="bgra4444" value="0x32314142" summary="16-bit BGRA format, [15:0] B:G:R:A 4:4:4:4 little endian"/>
++ <entry name="xrgb1555" value="0x35315258" summary="16-bit xRGB format, [15:0] x:R:G:B 1:5:5:5 little endian"/>
++ <entry name="xbgr1555" value="0x35314258" summary="16-bit xBGR 1555 format, [15:0] x:B:G:R 1:5:5:5 little endian"/>
++ <entry name="rgbx5551" value="0x35315852" summary="16-bit RGBx 5551 format, [15:0] R:G:B:x 5:5:5:1 little endian"/>
++ <entry name="bgrx5551" value="0x35315842" summary="16-bit BGRx 5551 format, [15:0] B:G:R:x 5:5:5:1 little endian"/>
++ <entry name="argb1555" value="0x35315241" summary="16-bit ARGB 1555 format, [15:0] A:R:G:B 1:5:5:5 little endian"/>
++ <entry name="abgr1555" value="0x35314241" summary="16-bit ABGR 1555 format, [15:0] A:B:G:R 1:5:5:5 little endian"/>
++ <entry name="rgba5551" value="0x35314152" summary="16-bit RGBA 5551 format, [15:0] R:G:B:A 5:5:5:1 little endian"/>
++ <entry name="bgra5551" value="0x35314142" summary="16-bit BGRA 5551 format, [15:0] B:G:R:A 5:5:5:1 little endian"/>
++ <entry name="rgb565" value="0x36314752" summary="16-bit RGB 565 format, [15:0] R:G:B 5:6:5 little endian"/>
++ <entry name="bgr565" value="0x36314742" summary="16-bit BGR 565 format, [15:0] B:G:R 5:6:5 little endian"/>
++ <entry name="rgb888" value="0x34324752" summary="24-bit RGB format, [23:0] R:G:B little endian"/>
++ <entry name="bgr888" value="0x34324742" summary="24-bit BGR format, [23:0] B:G:R little endian"/>
++ <entry name="xbgr8888" value="0x34324258" summary="32-bit xBGR format, [31:0] x:B:G:R 8:8:8:8 little endian"/>
++ <entry name="rgbx8888" value="0x34325852" summary="32-bit RGBx format, [31:0] R:G:B:x 8:8:8:8 little endian"/>
++ <entry name="bgrx8888" value="0x34325842" summary="32-bit BGRx format, [31:0] B:G:R:x 8:8:8:8 little endian"/>
++ <entry name="abgr8888" value="0x34324241" summary="32-bit ABGR format, [31:0] A:B:G:R 8:8:8:8 little endian"/>
++ <entry name="rgba8888" value="0x34324152" summary="32-bit RGBA format, [31:0] R:G:B:A 8:8:8:8 little endian"/>
++ <entry name="bgra8888" value="0x34324142" summary="32-bit BGRA format, [31:0] B:G:R:A 8:8:8:8 little endian"/>
++ <entry name="xrgb2101010" value="0x30335258" summary="32-bit xRGB format, [31:0] x:R:G:B 2:10:10:10 little endian"/>
++ <entry name="xbgr2101010" value="0x30334258" summary="32-bit xBGR format, [31:0] x:B:G:R 2:10:10:10 little endian"/>
++ <entry name="rgbx1010102" value="0x30335852" summary="32-bit RGBx format, [31:0] R:G:B:x 10:10:10:2 little endian"/>
++ <entry name="bgrx1010102" value="0x30335842" summary="32-bit BGRx format, [31:0] B:G:R:x 10:10:10:2 little endian"/>
++ <entry name="argb2101010" value="0x30335241" summary="32-bit ARGB format, [31:0] A:R:G:B 2:10:10:10 little endian"/>
++ <entry name="abgr2101010" value="0x30334241" summary="32-bit ABGR format, [31:0] A:B:G:R 2:10:10:10 little endian"/>
++ <entry name="rgba1010102" value="0x30334152" summary="32-bit RGBA format, [31:0] R:G:B:A 10:10:10:2 little endian"/>
++ <entry name="bgra1010102" value="0x30334142" summary="32-bit BGRA format, [31:0] B:G:R:A 10:10:10:2 little endian"/>
++ <entry name="yuyv" value="0x56595559" summary="packed YCbCr format, [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian"/>
++ <entry name="yvyu" value="0x55595659" summary="packed YCbCr format, [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian"/>
++ <entry name="uyvy" value="0x59565955" summary="packed YCbCr format, [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian"/>
++ <entry name="vyuy" value="0x59555956" summary="packed YCbCr format, [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian"/>
++ <entry name="ayuv" value="0x56555941" summary="packed AYCbCr format, [31:0] A:Y:Cb:Cr 8:8:8:8 little endian"/>
++ <entry name="nv12" value="0x3231564e" summary="2 plane YCbCr Cr:Cb format, 2x2 subsampled Cr:Cb plane"/>
++ <entry name="nv21" value="0x3132564e" summary="2 plane YCbCr Cb:Cr format, 2x2 subsampled Cb:Cr plane"/>
++ <entry name="nv16" value="0x3631564e" summary="2 plane YCbCr Cr:Cb format, 2x1 subsampled Cr:Cb plane"/>
++ <entry name="nv61" value="0x3136564e" summary="2 plane YCbCr Cb:Cr format, 2x1 subsampled Cb:Cr plane"/>
++ <entry name="yuv410" value="0x39565559" summary="3 plane YCbCr format, 4x4 subsampled Cb (1) and Cr (2) planes"/>
++ <entry name="yvu410" value="0x39555659" summary="3 plane YCbCr format, 4x4 subsampled Cr (1) and Cb (2) planes"/>
++ <entry name="yuv411" value="0x31315559" summary="3 plane YCbCr format, 4x1 subsampled Cb (1) and Cr (2) planes"/>
++ <entry name="yvu411" value="0x31315659" summary="3 plane YCbCr format, 4x1 subsampled Cr (1) and Cb (2) planes"/>
++ <entry name="yuv420" value="0x32315559" summary="3 plane YCbCr format, 2x2 subsampled Cb (1) and Cr (2) planes"/>
++ <entry name="yvu420" value="0x32315659" summary="3 plane YCbCr format, 2x2 subsampled Cr (1) and Cb (2) planes"/>
++ <entry name="yuv422" value="0x36315559" summary="3 plane YCbCr format, 2x1 subsampled Cb (1) and Cr (2) planes"/>
++ <entry name="yvu422" value="0x36315659" summary="3 plane YCbCr format, 2x1 subsampled Cr (1) and Cb (2) planes"/>
++ <entry name="yuv444" value="0x34325559" summary="3 plane YCbCr format, non-subsampled Cb (1) and Cr (2) planes"/>
++ <entry name="yvu444" value="0x34325659" summary="3 plane YCbCr format, non-subsampled Cr (1) and Cb (2) planes"/>
++ </enum>
++
++ <request name="create_pool">
++ <description summary="create a shm pool">
++ Create a new wl_shm_pool object.
++
++ The pool can be used to create shared memory based buffer
++ objects. The server will mmap size bytes of the passed file
++ descriptor, to use as backing memory for the pool.
++ </description>
++ <arg name="id" type="new_id" interface="wl_shm_pool" summary="pool to create"/>
++ <arg name="fd" type="fd" summary="file descriptor for the pool"/>
++ <arg name="size" type="int" summary="pool size, in bytes"/>
++ </request>
++
++ <event name="format">
++ <description summary="pixel format description">
++ Informs the client about a valid pixel format that
++ can be used for buffers. Known formats include
++ argb8888 and xrgb8888.
++ </description>
++ <arg name="format" type="uint" enum="format" summary="buffer pixel format"/>
++ </event>
++ </interface>
++
++ <interface name="wl_buffer" version="1">
++ <description summary="content for a wl_surface">
++ A buffer provides the content for a wl_surface. Buffers are
++ created through factory interfaces such as wl_drm, wl_shm or
++ similar. It has a width and a height and can be attached to a
++ wl_surface, but the mechanism by which a client provides and
++ updates the contents is defined by the buffer factory interface.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy a buffer">
++ Destroy a buffer. If and how you need to release the backing
++ storage is defined by the buffer factory interface.
++
++ For possible side-effects to a surface, see wl_surface.attach.
++ </description>
++ </request>
++
++ <event name="release">
++ <description summary="compositor releases buffer">
++ Sent when this wl_buffer is no longer used by the compositor.
++ The client is now free to reuse or destroy this buffer and its
++ backing storage.
++
++ If a client receives a release event before the frame callback
++ requested in the same wl_surface.commit that attaches this
++ wl_buffer to a surface, then the client is immediately free to
++ reuse the buffer and its backing storage, and does not need a
++ second buffer for the next surface content update. Typically
++ this is possible, when the compositor maintains a copy of the
++ wl_surface contents, e.g. as a GL texture. This is an important
++ optimization for GL(ES) compositors with wl_shm clients.
++ </description>
++ </event>
++ </interface>
++
++ <interface name="wl_data_offer" version="3">
++ <description summary="offer to transfer data">
++ A wl_data_offer represents a piece of data offered for transfer
++ by another client (the source client). It is used by the
++ copy-and-paste and drag-and-drop mechanisms. The offer
++ describes the different mime types that the data can be
++ converted to and provides the mechanism for transferring the
++ data directly from the source client.
++ </description>
++
++ <enum name="error">
++ <entry name="invalid_finish" value="0"
++ summary="finish request was called untimely"/>
++ <entry name="invalid_action_mask" value="1"
++ summary="action mask contains invalid values"/>
++ <entry name="invalid_action" value="2"
++ summary="action argument has an invalid value"/>
++ <entry name="invalid_offer" value="3"
++ summary="offer doesn't accept this request"/>
++ </enum>
++
++ <request name="accept">
++ <description summary="accept one of the offered mime types">
++ Indicate that the client can accept the given mime type, or
++ NULL for not accepted.
++
++ For objects of version 2 or older, this request is used by the
++ client to give feedback whether the client can receive the given
++ mime type, or NULL if none is accepted; the feedback does not
++ determine whether the drag-and-drop operation succeeds or not.
++
++ For objects of version 3 or newer, this request determines the
++ final result of the drag-and-drop operation. If the end result
++ is that no mime types were accepted, the drag-and-drop operation
++ will be cancelled and the corresponding drag source will receive
++ wl_data_source.cancelled. Clients may still use this event in
++ conjunction with wl_data_source.action for feedback.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the accept request"/>
++ <arg name="mime_type" type="string" allow-null="true" summary="mime type accepted by the client"/>
++ </request>
++
++ <request name="receive">
++ <description summary="request that the data is transferred">
++ To transfer the offered data, the client issues this request
++ and indicates the mime type it wants to receive. The transfer
++ happens through the passed file descriptor (typically created
++ with the pipe system call). The source client writes the data
++ in the mime type representation requested and then closes the
++ file descriptor.
++
++ The receiving client reads from the read end of the pipe until
++ EOF and then closes its end, at which point the transfer is
++ complete.
++
++ This request may happen multiple times for different mime types,
++ both before and after wl_data_device.drop. Drag-and-drop destination
++ clients may preemptively fetch data or examine it more closely to
++ determine acceptance.
++ </description>
++ <arg name="mime_type" type="string" summary="mime type desired by receiver"/>
++ <arg name="fd" type="fd" summary="file descriptor for data transfer"/>
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy data offer">
++ Destroy the data offer.
++ </description>
++ </request>
++
++ <event name="offer">
++ <description summary="advertise offered mime type">
++ Sent immediately after creating the wl_data_offer object. One
++ event per offered mime type.
++ </description>
++ <arg name="mime_type" type="string" summary="offered mime type"/>
++ </event>
++
++ <!-- Version 3 additions -->
++
++ <request name="finish" since="3">
++ <description summary="the offer will no longer be used">
++ Notifies the compositor that the drag destination successfully
++ finished the drag-and-drop operation.
++
++ Upon receiving this request, the compositor will emit
++ wl_data_source.dnd_finished on the drag source client.
++
++ It is a client error to perform other requests than
++ wl_data_offer.destroy after this one. It is also an error to perform
++ this request after a NULL mime type has been set in
++ wl_data_offer.accept or no action was received through
++ wl_data_offer.action.
++ </description>
++ </request>
++
++ <request name="set_actions" since="3">
++ <description summary="set the available/preferred drag-and-drop actions">
++ Sets the actions that the destination side client supports for
++ this operation. This request may trigger the emission of
++ wl_data_source.action and wl_data_offer.action events if the compositor
++ needs to change the selected action.
++
++ This request can be called multiple times throughout the
++ drag-and-drop operation, typically in response to wl_data_device.enter
++ or wl_data_device.motion events.
++
++ This request determines the final result of the drag-and-drop
++ operation. If the end result is that no action is accepted,
++ the drag source will receive wl_drag_source.cancelled.
++
++ The dnd_actions argument must contain only values expressed in the
++ wl_data_device_manager.dnd_actions enum, and the preferred_action
++ argument must only contain one of those values set, otherwise it
++ will result in a protocol error.
++
++ While managing an "ask" action, the destination drag-and-drop client
++ may perform further wl_data_offer.receive requests, and is expected
++ to perform one last wl_data_offer.set_actions request with a preferred
++ action other than "ask" (and optionally wl_data_offer.accept) before
++ requesting wl_data_offer.finish, in order to convey the action selected
++ by the user. If the preferred action is not in the
++ wl_data_offer.source_actions mask, an error will be raised.
++
++ If the "ask" action is dismissed (e.g. user cancellation), the client
++ is expected to perform wl_data_offer.destroy right away.
++
++ This request can only be made on drag-and-drop offers, a protocol error
++ will be raised otherwise.
++ </description>
++ <arg name="dnd_actions" type="uint" summary="actions supported by the destination client"/>
++ <arg name="preferred_action" type="uint" summary="action preferred by the destination client"/>
++ </request>
++
++ <event name="source_actions" since="3">
++ <description summary="notify the source-side available actions">
++ This event indicates the actions offered by the data source. It
++ will be sent right after wl_data_device.enter, or anytime the source
++ side changes its offered actions through wl_data_source.set_actions.
++ </description>
++ <arg name="source_actions" type="uint" summary="actions offered by the data source"/>
++ </event>
++
++ <event name="action" since="3">
++ <description summary="notify the selected action">
++ This event indicates the action selected by the compositor after
++ matching the source/destination side actions. Only one action (or
++ none) will be offered here.
++
++ This event can be emitted multiple times during the drag-and-drop
++ operation in response to destination side action changes through
++ wl_data_offer.set_actions.
++
++ This event will no longer be emitted after wl_data_device.drop
++ happened on the drag-and-drop destination, the client must
++ honor the last action received, or the last preferred one set
++ through wl_data_offer.set_actions when handling an "ask" action.
++
++ Compositors may also change the selected action on the fly, mainly
++ in response to keyboard modifier changes during the drag-and-drop
++ operation.
++
++ The most recent action received is always the valid one. Prior to
++ receiving wl_data_device.drop, the chosen action may change (e.g.
++ due to keyboard modifiers being pressed). At the time of receiving
++ wl_data_device.drop the drag-and-drop destination must honor the
++ last action received.
++
++ Action changes may still happen after wl_data_device.drop,
++ especially on "ask" actions, where the drag-and-drop destination
++ may choose another action afterwards. Action changes happening
++ at this stage are always the result of inter-client negotiation, the
++ compositor shall no longer be able to induce a different action.
++
++ Upon "ask" actions, it is expected that the drag-and-drop destination
++ may potentially choose a different action and/or mime type,
++ based on wl_data_offer.source_actions and finally chosen by the
++ user (e.g. popping up a menu with the available options). The
++ final wl_data_offer.set_actions and wl_data_offer.accept requests
++ must happen before the call to wl_data_offer.finish.
++ </description>
++ <arg name="dnd_action" type="uint" summary="action selected by the compositor"/>
++ </event>
++ </interface>
++
++ <interface name="wl_data_source" version="3">
++ <description summary="offer to transfer data">
++ The wl_data_source object is the source side of a wl_data_offer.
++ It is created by the source client in a data transfer and
++ provides a way to describe the offered data and a way to respond
++ to requests to transfer the data.
++ </description>
++
++ <enum name="error">
++ <entry name="invalid_action_mask" value="0"
++ summary="action mask contains invalid values"/>
++ <entry name="invalid_source" value="1"
++ summary="source doesn't accept this request"/>
++ </enum>
++
++ <request name="offer">
++ <description summary="add an offered mime type">
++ This request adds a mime type to the set of mime types
++ advertised to targets. Can be called several times to offer
++ multiple types.
++ </description>
++ <arg name="mime_type" type="string" summary="mime type offered by the data source"/>
++ </request>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy the data source">
++ Destroy the data source.
++ </description>
++ </request>
++
++ <event name="target">
++ <description summary="a target accepts an offered mime type">
++ Sent when a target accepts pointer_focus or motion events. If
++ a target does not accept any of the offered types, type is NULL.
++
++ Used for feedback during drag-and-drop.
++ </description>
++ <arg name="mime_type" type="string" allow-null="true" summary="mime type accepted by the target"/>
++ </event>
++
++ <event name="send">
++ <description summary="send the data">
++ Request for data from the client. Send the data as the
++ specified mime type over the passed file descriptor, then
++ close it.
++ </description>
++ <arg name="mime_type" type="string" summary="mime type for the data"/>
++ <arg name="fd" type="fd" summary="file descriptor for the data"/>
++ </event>
++
++ <event name="cancelled">
++ <description summary="selection was cancelled">
++ This data source is no longer valid. There are several reasons why
++ this could happen:
++
++ - The data source has been replaced by another data source.
++ - The drag-and-drop operation was performed, but the drop destination
++ did not accept any of the mime types offered through
++ wl_data_source.target.
++ - The drag-and-drop operation was performed, but the drop destination
++ did not select any of the actions present in the mask offered through
++ wl_data_source.action.
++ - The drag-and-drop operation was performed but didn't happen over a
++ surface.
++ - The compositor cancelled the drag-and-drop operation (e.g. compositor
++ dependent timeouts to avoid stale drag-and-drop transfers).
++
++ The client should clean up and destroy this data source.
++
++ For objects of version 2 or older, wl_data_source.cancelled will
++ only be emitted if the data source was replaced by another data
++ source.
++ </description>
++ </event>
++
++ <!-- Version 3 additions -->
++
++ <request name="set_actions" since="3">
++ <description summary="set the available drag-and-drop actions">
++ Sets the actions that the source side client supports for this
++ operation. This request may trigger wl_data_source.action and
++ wl_data_offer.action events if the compositor needs to change the
++ selected action.
++
++ The dnd_actions argument must contain only values expressed in the
++ wl_data_device_manager.dnd_actions enum, otherwise it will result
++ in a protocol error.
++
++ This request must be made once only, and can only be made on sources
++ used in drag-and-drop, so it must be performed before
++ wl_data_device.start_drag. Attempting to use the source other than
++ for drag-and-drop will raise a protocol error.
++ </description>
++ <arg name="dnd_actions" type="uint" summary="actions supported by the data source"/>
++ </request>
++
++ <event name="dnd_drop_performed" since="3">
++ <description summary="the drag-and-drop operation physically finished">
++ The user performed the drop action. This event does not indicate
++ acceptance, wl_data_source.cancelled may still be emitted afterwards
++ if the drop destination does not accept any mime type.
++
++ However, this event might however not be received if the compositor
++ cancelled the drag-and-drop operation before this event could happen.
++
++ Note that the data_source may still be used in the future and should
++ not be destroyed here.
++ </description>
++ </event>
++
++ <event name="dnd_finished" since="3">
++ <description summary="the drag-and-drop operation concluded">
++ The drop destination finished interoperating with this data
++ source, so the client is now free to destroy this data source and
++ free all associated data.
++
++ If the action used to perform the operation was "move", the
++ source can now delete the transferred data.
++ </description>
++ </event>
++
++ <event name="action" since="3">
++ <description summary="notify the selected action">
++ This event indicates the action selected by the compositor after
++ matching the source/destination side actions. Only one action (or
++ none) will be offered here.
++
++ This event can be emitted multiple times during the drag-and-drop
++ operation, mainly in response to destination side changes through
++ wl_data_offer.set_actions, and as the data device enters/leaves
++ surfaces.
++
++ It is only possible to receive this event after
++ wl_data_source.dnd_drop_performed if the drag-and-drop operation
++ ended in an "ask" action, in which case the final wl_data_source.action
++ event will happen immediately before wl_data_source.dnd_finished.
++
++ Compositors may also change the selected action on the fly, mainly
++ in response to keyboard modifier changes during the drag-and-drop
++ operation.
++
++ The most recent action received is always the valid one. The chosen
++ action may change alongside negotiation (e.g. an "ask" action can turn
++ into a "move" operation), so the effects of the final action must
++ always be applied in wl_data_offer.dnd_finished.
++
++ Clients can trigger cursor surface changes from this point, so
++ they reflect the current action.
++ </description>
++ <arg name="dnd_action" type="uint" summary="action selected by the compositor"/>
++ </event>
++ </interface>
++
++ <interface name="wl_data_device" version="3">
++ <description summary="data transfer device">
++ There is one wl_data_device per seat which can be obtained
++ from the global wl_data_device_manager singleton.
++
++ A wl_data_device provides access to inter-client data transfer
++ mechanisms such as copy-and-paste and drag-and-drop.
++ </description>
++
++ <enum name="error">
++ <entry name="role" value="0" summary="given wl_surface has another role"/>
++ </enum>
++
++ <request name="start_drag">
++ <description summary="start drag-and-drop operation">
++ This request asks the compositor to start a drag-and-drop
++ operation on behalf of the client.
++
++ The source argument is the data source that provides the data
++ for the eventual data transfer. If source is NULL, enter, leave
++ and motion events are sent only to the client that initiated the
++ drag and the client is expected to handle the data passing
++ internally.
++
++ The origin surface is the surface where the drag originates and
++ the client must have an active implicit grab that matches the
++ serial.
++
++ The icon surface is an optional (can be NULL) surface that
++ provides an icon to be moved around with the cursor. Initially,
++ the top-left corner of the icon surface is placed at the cursor
++ hotspot, but subsequent wl_surface.attach request can move the
++ relative position. Attach requests must be confirmed with
++ wl_surface.commit as usual. The icon surface is given the role of
++ a drag-and-drop icon. If the icon surface already has another role,
++ it raises a protocol error.
++
++ The current and pending input regions of the icon wl_surface are
++ cleared, and wl_surface.set_input_region is ignored until the
++ wl_surface is no longer used as the icon surface. When the use
++ as an icon ends, the current and pending input regions become
++ undefined, and the wl_surface is unmapped.
++ </description>
++ <arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the eventual transfer"/>
++ <arg name="origin" type="object" interface="wl_surface" summary="surface where the drag originates"/>
++ <arg name="icon" type="object" interface="wl_surface" allow-null="true" summary="drag-and-drop icon surface"/>
++ <arg name="serial" type="uint" summary="serial number of the implicit grab on the origin"/>
++ </request>
++
++ <request name="set_selection">
++ <description summary="copy data to the selection">
++ This request asks the compositor to set the selection
++ to the data from the source on behalf of the client.
++
++ To unset the selection, set the source to NULL.
++ </description>
++ <arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the selection"/>
++ <arg name="serial" type="uint" summary="serial number of the event that triggered this request"/>
++ </request>
++
++ <event name="data_offer">
++ <description summary="introduce a new wl_data_offer">
++ The data_offer event introduces a new wl_data_offer object,
++ which will subsequently be used in either the
++ data_device.enter event (for drag-and-drop) or the
++ data_device.selection event (for selections). Immediately
++ following the data_device.data_offer event, the new data_offer
++ object will send out data_offer.offer events to describe the
++ mime types it offers.
++ </description>
++ <arg name="id" type="new_id" interface="wl_data_offer" summary="the new data_offer object"/>
++ </event>
++
++ <event name="enter">
++ <description summary="initiate drag-and-drop session">
++ This event is sent when an active drag-and-drop pointer enters
++ a surface owned by the client. The position of the pointer at
++ enter time is provided by the x and y arguments, in surface-local
++ coordinates.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the enter event"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="client surface entered"/>
++ <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++ <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++ <arg name="id" type="object" interface="wl_data_offer" allow-null="true"
++ summary="source data_offer object"/>
++ </event>
++
++ <event name="leave">
++ <description summary="end drag-and-drop session">
++ This event is sent when the drag-and-drop pointer leaves the
++ surface and the session ends. The client must destroy the
++ wl_data_offer introduced at enter time at this point.
++ </description>
++ </event>
++
++ <event name="motion">
++ <description summary="drag-and-drop session motion">
++ This event is sent when the drag-and-drop pointer moves within
++ the currently focused surface. The new position of the pointer
++ is provided by the x and y arguments, in surface-local
++ coordinates.
++ </description>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++ <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++ </event>
++
++ <event name="drop">
++ <description summary="end drag-and-drop session successfully">
++ The event is sent when a drag-and-drop operation is ended
++ because the implicit grab is removed.
++
++ The drag-and-drop destination is expected to honor the last action
++ received through wl_data_offer.action, if the resulting action is
++ "copy" or "move", the destination can still perform
++ wl_data_offer.receive requests, and is expected to end all
++ transfers with a wl_data_offer.finish request.
++
++ If the resulting action is "ask", the action will not be considered
++ final. The drag-and-drop destination is expected to perform one last
++ wl_data_offer.set_actions request, or wl_data_offer.destroy in order
++ to cancel the operation.
++ </description>
++ </event>
++
++ <event name="selection">
++ <description summary="advertise new selection">
++ The selection event is sent out to notify the client of a new
++ wl_data_offer for the selection for this device. The
++ data_device.data_offer and the data_offer.offer events are
++ sent out immediately before this event to introduce the data
++ offer object. The selection event is sent to a client
++ immediately before receiving keyboard focus and when a new
++ selection is set while the client has keyboard focus. The
++ data_offer is valid until a new data_offer or NULL is received
++ or until the client loses keyboard focus. The client must
++ destroy the previous selection data_offer, if any, upon receiving
++ this event.
++ </description>
++ <arg name="id" type="object" interface="wl_data_offer" allow-null="true"
++ summary="selection data_offer object"/>
++ </event>
++
++ <!-- Version 2 additions -->
++
++ <request name="release" type="destructor" since="2">
++ <description summary="destroy data device">
++ This request destroys the data device.
++ </description>
++ </request>
++ </interface>
++
++ <interface name="wl_data_device_manager" version="3">
++ <description summary="data transfer interface">
++ The wl_data_device_manager is a singleton global object that
++ provides access to inter-client data transfer mechanisms such as
++ copy-and-paste and drag-and-drop. These mechanisms are tied to
++ a wl_seat and this interface lets a client get a wl_data_device
++ corresponding to a wl_seat.
++
++ Depending on the version bound, the objects created from the bound
++ wl_data_device_manager object will have different requirements for
++ functioning properly. See wl_data_source.set_actions,
++ wl_data_offer.accept and wl_data_offer.finish for details.
++ </description>
++
++ <request name="create_data_source">
++ <description summary="create a new data source">
++ Create a new data source.
++ </description>
++ <arg name="id" type="new_id" interface="wl_data_source" summary="data source to create"/>
++ </request>
++
++ <request name="get_data_device">
++ <description summary="create a new data device">
++ Create a new data device for a given seat.
++ </description>
++ <arg name="id" type="new_id" interface="wl_data_device" summary="data device to create"/>
++ <arg name="seat" type="object" interface="wl_seat" summary="seat associated with the data device"/>
++ </request>
++
++ <!-- Version 3 additions -->
++
++ <enum name="dnd_action" bitfield="true" since="3">
++ <description summary="drag and drop actions">
++ This is a bitmask of the available/preferred actions in a
++ drag-and-drop operation.
++
++ In the compositor, the selected action is a result of matching the
++ actions offered by the source and destination sides. "action" events
++ with a "none" action will be sent to both source and destination if
++ there is no match. All further checks will effectively happen on
++ (source actions ∩ destination actions).
++
++ In addition, compositors may also pick different actions in
++ reaction to key modifiers being pressed. One common design that
++ is used in major toolkits (and the behavior recommended for
++ compositors) is:
++
++ - If no modifiers are pressed, the first match (in bit order)
++ will be used.
++ - Pressing Shift selects "move", if enabled in the mask.
++ - Pressing Control selects "copy", if enabled in the mask.
++
++ Behavior beyond that is considered implementation-dependent.
++ Compositors may for example bind other modifiers (like Alt/Meta)
++ or drags initiated with other buttons than BTN_LEFT to specific
++ actions (e.g. "ask").
++ </description>
++ <entry name="none" value="0" summary="no action"/>
++ <entry name="copy" value="1" summary="copy action"/>
++ <entry name="move" value="2" summary="move action"/>
++ <entry name="ask" value="4" summary="ask action"/>
++ </enum>
++ </interface>
++
++ <interface name="wl_shell" version="1">
++ <description summary="create desktop-style surfaces">
++ This interface is implemented by servers that provide
++ desktop-style user interfaces.
++
++ It allows clients to associate a wl_shell_surface with
++ a basic surface.
++ </description>
++
++ <enum name="error">
++ <entry name="role" value="0" summary="given wl_surface has another role"/>
++ </enum>
++
++ <request name="get_shell_surface">
++ <description summary="create a shell surface from a surface">
++ Create a shell surface for an existing surface. This gives
++ the wl_surface the role of a shell surface. If the wl_surface
++ already has another role, it raises a protocol error.
++
++ Only one shell surface can be associated with a given surface.
++ </description>
++ <arg name="id" type="new_id" interface="wl_shell_surface" summary="shell surface to create"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="surface to be given the shell surface role"/>
++ </request>
++ </interface>
++
++ <interface name="wl_shell_surface" version="1">
++ <description summary="desktop-style metadata interface">
++ An interface that may be implemented by a wl_surface, for
++ implementations that provide a desktop-style user interface.
++
++ It provides requests to treat surfaces like toplevel, fullscreen
++ or popup windows, move, resize or maximize them, associate
++ metadata like title and class, etc.
++
++ On the server side the object is automatically destroyed when
++ the related wl_surface is destroyed. On the client side,
++ wl_shell_surface_destroy() must be called before destroying
++ the wl_surface object.
++ </description>
++
++ <request name="pong">
++ <description summary="respond to a ping event">
++ A client must respond to a ping event with a pong request or
++ the client may be deemed unresponsive.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the ping event"/>
++ </request>
++
++ <request name="move">
++ <description summary="start an interactive move">
++ Start a pointer-driven move of the surface.
++
++ This request must be used in response to a button press event.
++ The server may ignore move requests depending on the state of
++ the surface (e.g. fullscreen or maximized).
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="seat whose pointer is used"/>
++ <arg name="serial" type="uint" summary="serial number of the implicit grab on the pointer"/>
++ </request>
++
++ <enum name="resize" bitfield="true">
++ <description summary="edge values for resizing">
++ These values are used to indicate which edge of a surface
++ is being dragged in a resize operation. The server may
++ use this information to adapt its behavior, e.g. choose
++ an appropriate cursor image.
++ </description>
++ <entry name="none" value="0" summary="no edge"/>
++ <entry name="top" value="1" summary="top edge"/>
++ <entry name="bottom" value="2" summary="bottom edge"/>
++ <entry name="left" value="4" summary="left edge"/>
++ <entry name="top_left" value="5" summary="top and left edges"/>
++ <entry name="bottom_left" value="6" summary="bottom and left edges"/>
++ <entry name="right" value="8" summary="right edge"/>
++ <entry name="top_right" value="9" summary="top and right edges"/>
++ <entry name="bottom_right" value="10" summary="bottom and right edges"/>
++ </enum>
++
++ <request name="resize">
++ <description summary="start an interactive resize">
++ Start a pointer-driven resizing of the surface.
++
++ This request must be used in response to a button press event.
++ The server may ignore resize requests depending on the state of
++ the surface (e.g. fullscreen or maximized).
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="seat whose pointer is used"/>
++ <arg name="serial" type="uint" summary="serial number of the implicit grab on the pointer"/>
++ <arg name="edges" type="uint" enum="resize" summary="which edge or corner is being dragged"/>
++ </request>
++
++ <request name="set_toplevel">
++ <description summary="make the surface a toplevel surface">
++ Map the surface as a toplevel surface.
++
++ A toplevel surface is not fullscreen, maximized or transient.
++ </description>
++ </request>
++
++ <enum name="transient" bitfield="true">
++ <description summary="details of transient behaviour">
++ These flags specify details of the expected behaviour
++ of transient surfaces. Used in the set_transient request.
++ </description>
++ <entry name="inactive" value="0x1" summary="do not set keyboard focus"/>
++ </enum>
++
++ <request name="set_transient">
++ <description summary="make the surface a transient surface">
++ Map the surface relative to an existing surface.
++
++ The x and y arguments specify the location of the upper left
++ corner of the surface relative to the upper left corner of the
++ parent surface, in surface-local coordinates.
++
++ The flags argument controls details of the transient behaviour.
++ </description>
++ <arg name="parent" type="object" interface="wl_surface" summary="parent surface"/>
++ <arg name="x" type="int" summary="surface-local x coordinate"/>
++ <arg name="y" type="int" summary="surface-local y coordinate"/>
++ <arg name="flags" type="uint" enum="transient" summary="transient surface behavior"/>
++ </request>
++
++ <enum name="fullscreen_method">
++ <description summary="different method to set the surface fullscreen">
++ Hints to indicate to the compositor how to deal with a conflict
++ between the dimensions of the surface and the dimensions of the
++ output. The compositor is free to ignore this parameter.
++ </description>
++ <entry name="default" value="0" summary="no preference, apply default policy"/>
++ <entry name="scale" value="1" summary="scale, preserve the surface's aspect ratio and center on output"/>
++ <entry name="driver" value="2" summary="switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch"/>
++ <entry name="fill" value="3" summary="no upscaling, center on output and add black borders to compensate size mismatch"/>
++ </enum>
++
++ <request name="set_fullscreen">
++ <description summary="make the surface a fullscreen surface">
++ Map the surface as a fullscreen surface.
++
++ If an output parameter is given then the surface will be made
++ fullscreen on that output. If the client does not specify the
++ output then the compositor will apply its policy - usually
++ choosing the output on which the surface has the biggest surface
++ area.
++
++ The client may specify a method to resolve a size conflict
++ between the output size and the surface size - this is provided
++ through the method parameter.
++
++ The framerate parameter is used only when the method is set
++ to "driver", to indicate the preferred framerate. A value of 0
++ indicates that the client does not care about framerate. The
++ framerate is specified in mHz, that is framerate of 60000 is 60Hz.
++
++ A method of "scale" or "driver" implies a scaling operation of
++ the surface, either via a direct scaling operation or a change of
++ the output mode. This will override any kind of output scaling, so
++ that mapping a surface with a buffer size equal to the mode can
++ fill the screen independent of buffer_scale.
++
++ A method of "fill" means we don't scale up the buffer, however
++ any output scale is applied. This means that you may run into
++ an edge case where the application maps a buffer with the same
++ size of the output mode but buffer_scale 1 (thus making a
++ surface larger than the output). In this case it is allowed to
++ downscale the results to fit the screen.
++
++ The compositor must reply to this request with a configure event
++ with the dimensions for the output on which the surface will
++ be made fullscreen.
++ </description>
++ <arg name="method" type="uint" enum="fullscreen_method" summary="method for resolving size conflict"/>
++ <arg name="framerate" type="uint" summary="framerate in mHz"/>
++ <arg name="output" type="object" interface="wl_output" allow-null="true"
++ summary="output on which the surface is to be fullscreen"/>
++ </request>
++
++ <request name="set_popup">
++ <description summary="make the surface a popup surface">
++ Map the surface as a popup.
++
++ A popup surface is a transient surface with an added pointer
++ grab.
++
++ An existing implicit grab will be changed to owner-events mode,
++ and the popup grab will continue after the implicit grab ends
++ (i.e. releasing the mouse button does not cause the popup to
++ be unmapped).
++
++ The popup grab continues until the window is destroyed or a
++ mouse button is pressed in any other client's window. A click
++ in any of the client's surfaces is reported as normal, however,
++ clicks in other clients' surfaces will be discarded and trigger
++ the callback.
++
++ The x and y arguments specify the location of the upper left
++ corner of the surface relative to the upper left corner of the
++ parent surface, in surface-local coordinates.
++ </description>
++ <arg name="seat" type="object" interface="wl_seat" summary="seat whose pointer is used"/>
++ <arg name="serial" type="uint" summary="serial number of the implicit grab on the pointer"/>
++ <arg name="parent" type="object" interface="wl_surface" summary="parent surface"/>
++ <arg name="x" type="int" summary="surface-local x coordinate"/>
++ <arg name="y" type="int" summary="surface-local y coordinate"/>
++ <arg name="flags" type="uint" enum="transient" summary="transient surface behavior"/>
++ </request>
++
++ <request name="set_maximized">
++ <description summary="make the surface a maximized surface">
++ Map the surface as a maximized surface.
++
++ If an output parameter is given then the surface will be
++ maximized on that output. If the client does not specify the
++ output then the compositor will apply its policy - usually
++ choosing the output on which the surface has the biggest surface
++ area.
++
++ The compositor will reply with a configure event telling
++ the expected new surface size. The operation is completed
++ on the next buffer attach to this surface.
++
++ A maximized surface typically fills the entire output it is
++ bound to, except for desktop elements such as panels. This is
++ the main difference between a maximized shell surface and a
++ fullscreen shell surface.
++
++ The details depend on the compositor implementation.
++ </description>
++ <arg name="output" type="object" interface="wl_output" allow-null="true"
++ summary="output on which the surface is to be maximized"/>
++ </request>
++
++ <request name="set_title">
++ <description summary="set surface title">
++ Set a short title for the surface.
++
++ This string may be used to identify the surface in a task bar,
++ window list, or other user interface elements provided by the
++ compositor.
++
++ The string must be encoded in UTF-8.
++ </description>
++ <arg name="title" type="string" summary="surface title"/>
++ </request>
++
++ <request name="set_class">
++ <description summary="set surface class">
++ Set a class for the surface.
++
++ The surface class identifies the general class of applications
++ to which the surface belongs. A common convention is to use the
++ file name (or the full path if it is a non-standard location) of
++ the application's .desktop file as the class.
++ </description>
++ <arg name="class_" type="string" summary="surface class"/>
++ </request>
++
++ <event name="ping">
++ <description summary="ping client">
++ Ping a client to check if it is receiving events and sending
++ requests. A client is expected to reply with a pong request.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the ping"/>
++ </event>
++
++ <event name="configure">
++ <description summary="suggest resize">
++ The configure event asks the client to resize its surface.
++
++ The size is a hint, in the sense that the client is free to
++ ignore it if it doesn't resize, pick a smaller size (to
++ satisfy aspect ratio or resize in steps of NxM pixels).
++
++ The edges parameter provides a hint about how the surface
++ was resized. The client may use this information to decide
++ how to adjust its content to the new size (e.g. a scrolling
++ area might adjust its content position to leave the viewable
++ content unmoved).
++
++ The client is free to dismiss all but the last configure
++ event it received.
++
++ The width and height arguments specify the size of the window
++ in surface-local coordinates.
++ </description>
++ <arg name="edges" type="uint" enum="resize" summary="how the surface was resized"/>
++ <arg name="width" type="int" summary="new width of the surface"/>
++ <arg name="height" type="int" summary="new height of the surface"/>
++ </event>
++
++ <event name="popup_done">
++ <description summary="popup interaction is done">
++ The popup_done event is sent out when a popup grab is broken,
++ that is, when the user clicks a surface that doesn't belong
++ to the client owning the popup surface.
++ </description>
++ </event>
++ </interface>
++
++ <interface name="wl_surface" version="4">
++ <description summary="an onscreen surface">
++ A surface is a rectangular area that is displayed on the screen.
++ It has a location, size and pixel contents.
++
++ The size of a surface (and relative positions on it) is described
++ in surface-local coordinates, which may differ from the buffer
++ coordinates of the pixel content, in case a buffer_transform
++ or a buffer_scale is used.
++
++ A surface without a "role" is fairly useless: a compositor does
++ not know where, when or how to present it. The role is the
++ purpose of a wl_surface. Examples of roles are a cursor for a
++ pointer (as set by wl_pointer.set_cursor), a drag icon
++ (wl_data_device.start_drag), a sub-surface
++ (wl_subcompositor.get_subsurface), and a window as defined by a
++ shell protocol (e.g. wl_shell.get_shell_surface).
++
++ A surface can have only one role at a time. Initially a
++ wl_surface does not have a role. Once a wl_surface is given a
++ role, it is set permanently for the whole lifetime of the
++ wl_surface object. Giving the current role again is allowed,
++ unless explicitly forbidden by the relevant interface
++ specification.
++
++ Surface roles are given by requests in other interfaces such as
++ wl_pointer.set_cursor. The request should explicitly mention
++ that this request gives a role to a wl_surface. Often, this
++ request also creates a new protocol object that represents the
++ role and adds additional functionality to wl_surface. When a
++ client wants to destroy a wl_surface, they must destroy this 'role
++ object' before the wl_surface.
++
++ Destroying the role object does not remove the role from the
++ wl_surface, but it may stop the wl_surface from "playing the role".
++ For instance, if a wl_subsurface object is destroyed, the wl_surface
++ it was created for will be unmapped and forget its position and
++ z-order. It is allowed to create a wl_subsurface for the same
++ wl_surface again, but it is not allowed to use the wl_surface as
++ a cursor (cursor is a different role than sub-surface, and role
++ switching is not allowed).
++ </description>
++
++ <enum name="error">
++ <description summary="wl_surface error values">
++ These errors can be emitted in response to wl_surface requests.
++ </description>
++ <entry name="invalid_scale" value="0" summary="buffer scale value is invalid"/>
++ <entry name="invalid_transform" value="1" summary="buffer transform value is invalid"/>
++ </enum>
++
++ <request name="destroy" type="destructor">
++ <description summary="delete surface">
++ Deletes the surface and invalidates its object ID.
++ </description>
++ </request>
++
++ <request name="attach">
++ <description summary="set the surface contents">
++ Set a buffer as the content of this surface.
++
++ The new size of the surface is calculated based on the buffer
++ size transformed by the inverse buffer_transform and the
++ inverse buffer_scale. This means that the supplied buffer
++ must be an integer multiple of the buffer_scale.
++
++ The x and y arguments specify the location of the new pending
++ buffer's upper left corner, relative to the current buffer's upper
++ left corner, in surface-local coordinates. In other words, the
++ x and y, combined with the new surface size define in which
++ directions the surface's size changes.
++
++ Surface contents are double-buffered state, see wl_surface.commit.
++
++ The initial surface contents are void; there is no content.
++ wl_surface.attach assigns the given wl_buffer as the pending
++ wl_buffer. wl_surface.commit makes the pending wl_buffer the new
++ surface contents, and the size of the surface becomes the size
++ calculated from the wl_buffer, as described above. After commit,
++ there is no pending buffer until the next attach.
++
++ Committing a pending wl_buffer allows the compositor to read the
++ pixels in the wl_buffer. The compositor may access the pixels at
++ any time after the wl_surface.commit request. When the compositor
++ will not access the pixels anymore, it will send the
++ wl_buffer.release event. Only after receiving wl_buffer.release,
++ the client may reuse the wl_buffer. A wl_buffer that has been
++ attached and then replaced by another attach instead of committed
++ will not receive a release event, and is not used by the
++ compositor.
++
++ Destroying the wl_buffer after wl_buffer.release does not change
++ the surface contents. However, if the client destroys the
++ wl_buffer before receiving the wl_buffer.release event, the surface
++ contents become undefined immediately.
++
++ If wl_surface.attach is sent with a NULL wl_buffer, the
++ following wl_surface.commit will remove the surface content.
++ </description>
++ <arg name="buffer" type="object" interface="wl_buffer" allow-null="true"
++ summary="buffer of surface contents"/>
++ <arg name="x" type="int" summary="surface-local x coordinate"/>
++ <arg name="y" type="int" summary="surface-local y coordinate"/>
++ </request>
++
++ <request name="damage">
++ <description summary="mark part of the surface damaged">
++ This request is used to describe the regions where the pending
++ buffer is different from the current surface contents, and where
++ the surface therefore needs to be repainted. The compositor
++ ignores the parts of the damage that fall outside of the surface.
++
++ Damage is double-buffered state, see wl_surface.commit.
++
++ The damage rectangle is specified in surface-local coordinates,
++ where x and y specify the upper left corner of the damage rectangle.
++
++ The initial value for pending damage is empty: no damage.
++ wl_surface.damage adds pending damage: the new pending damage
++ is the union of old pending damage and the given rectangle.
++
++ wl_surface.commit assigns pending damage as the current damage,
++ and clears pending damage. The server will clear the current
++ damage as it repaints the surface.
++
++ Alternatively, damage can be posted with wl_surface.damage_buffer
++ which uses buffer coordinates instead of surface coordinates,
++ and is probably the preferred and intuitive way of doing this.
++ </description>
++ <arg name="x" type="int" summary="surface-local x coordinate"/>
++ <arg name="y" type="int" summary="surface-local y coordinate"/>
++ <arg name="width" type="int" summary="width of damage rectangle"/>
++ <arg name="height" type="int" summary="height of damage rectangle"/>
++ </request>
++
++ <request name="frame">
++ <description summary="request a frame throttling hint">
++ Request a notification when it is a good time to start drawing a new
++ frame, by creating a frame callback. This is useful for throttling
++ redrawing operations, and driving animations.
++
++ When a client is animating on a wl_surface, it can use the 'frame'
++ request to get notified when it is a good time to draw and commit the
++ next frame of animation. If the client commits an update earlier than
++ that, it is likely that some updates will not make it to the display,
++ and the client is wasting resources by drawing too often.
++
++ The frame request will take effect on the next wl_surface.commit.
++ The notification will only be posted for one frame unless
++ requested again. For a wl_surface, the notifications are posted in
++ the order the frame requests were committed.
++
++ The server must send the notifications so that a client
++ will not send excessive updates, while still allowing
++ the highest possible update rate for clients that wait for the reply
++ before drawing again. The server should give some time for the client
++ to draw and commit after sending the frame callback events to let it
++ hit the next output refresh.
++
++ A server should avoid signaling the frame callbacks if the
++ surface is not visible in any way, e.g. the surface is off-screen,
++ or completely obscured by other opaque surfaces.
++
++ The object returned by this request will be destroyed by the
++ compositor after the callback is fired and as such the client must not
++ attempt to use it after that point.
++
++ The callback_data passed in the callback is the current time, in
++ milliseconds, with an undefined base.
++ </description>
++ <arg name="callback" type="new_id" interface="wl_callback" summary="callback object for the frame request"/>
++ </request>
++
++ <request name="set_opaque_region">
++ <description summary="set opaque region">
++ This request sets the region of the surface that contains
++ opaque content.
++
++ The opaque region is an optimization hint for the compositor
++ that lets it optimize the redrawing of content behind opaque
++ regions. Setting an opaque region is not required for correct
++ behaviour, but marking transparent content as opaque will result
++ in repaint artifacts.
++
++ The opaque region is specified in surface-local coordinates.
++
++ The compositor ignores the parts of the opaque region that fall
++ outside of the surface.
++
++ Opaque region is double-buffered state, see wl_surface.commit.
++
++ wl_surface.set_opaque_region changes the pending opaque region.
++ wl_surface.commit copies the pending region to the current region.
++ Otherwise, the pending and current regions are never changed.
++
++ The initial value for an opaque region is empty. Setting the pending
++ opaque region has copy semantics, and the wl_region object can be
++ destroyed immediately. A NULL wl_region causes the pending opaque
++ region to be set to empty.
++ </description>
++ <arg name="region" type="object" interface="wl_region" allow-null="true"
++ summary="opaque region of the surface"/>
++ </request>
++
++ <request name="set_input_region">
++ <description summary="set input region">
++ This request sets the region of the surface that can receive
++ pointer and touch events.
++
++ Input events happening outside of this region will try the next
++ surface in the server surface stack. The compositor ignores the
++ parts of the input region that fall outside of the surface.
++
++ The input region is specified in surface-local coordinates.
++
++ Input region is double-buffered state, see wl_surface.commit.
++
++ wl_surface.set_input_region changes the pending input region.
++ wl_surface.commit copies the pending region to the current region.
++ Otherwise the pending and current regions are never changed,
++ except cursor and icon surfaces are special cases, see
++ wl_pointer.set_cursor and wl_data_device.start_drag.
++
++ The initial value for an input region is infinite. That means the
++ whole surface will accept input. Setting the pending input region
++ has copy semantics, and the wl_region object can be destroyed
++ immediately. A NULL wl_region causes the input region to be set
++ to infinite.
++ </description>
++ <arg name="region" type="object" interface="wl_region" allow-null="true"
++ summary="input region of the surface"/>
++ </request>
++
++ <request name="commit">
++ <description summary="commit pending surface state">
++ Surface state (input, opaque, and damage regions, attached buffers,
++ etc.) is double-buffered. Protocol requests modify the pending state,
++ as opposed to the current state in use by the compositor. A commit
++ request atomically applies all pending state, replacing the current
++ state. After commit, the new pending state is as documented for each
++ related request.
++
++ On commit, a pending wl_buffer is applied first, and all other state
++ second. This means that all coordinates in double-buffered state are
++ relative to the new wl_buffer coming into use, except for
++ wl_surface.attach itself. If there is no pending wl_buffer, the
++ coordinates are relative to the current surface contents.
++
++ All requests that need a commit to become effective are documented
++ to affect double-buffered state.
++
++ Other interfaces may add further double-buffered surface state.
++ </description>
++ </request>
++
++ <event name="enter">
++ <description summary="surface enters an output">
++ This is emitted whenever a surface's creation, movement, or resizing
++ results in some part of it being within the scanout region of an
++ output.
++
++ Note that a surface may be overlapping with zero or more outputs.
++ </description>
++ <arg name="output" type="object" interface="wl_output" summary="output entered by the surface"/>
++ </event>
++
++ <event name="leave">
++ <description summary="surface leaves an output">
++ This is emitted whenever a surface's creation, movement, or resizing
++ results in it no longer having any part of it within the scanout region
++ of an output.
++ </description>
++ <arg name="output" type="object" interface="wl_output" summary="output left by the surface"/>
++ </event>
++
++ <!-- Version 2 additions -->
++
++ <request name="set_buffer_transform" since="2">
++ <description summary="sets the buffer transformation">
++ This request sets an optional transformation on how the compositor
++ interprets the contents of the buffer attached to the surface. The
++ accepted values for the transform parameter are the values for
++ wl_output.transform.
++
++ Buffer transform is double-buffered state, see wl_surface.commit.
++
++ A newly created surface has its buffer transformation set to normal.
++
++ wl_surface.set_buffer_transform changes the pending buffer
++ transformation. wl_surface.commit copies the pending buffer
++ transformation to the current one. Otherwise, the pending and current
++ values are never changed.
++
++ The purpose of this request is to allow clients to render content
++ according to the output transform, thus permitting the compositor to
++ use certain optimizations even if the display is rotated. Using
++ hardware overlays and scanning out a client buffer for fullscreen
++ surfaces are examples of such optimizations. Those optimizations are
++ highly dependent on the compositor implementation, so the use of this
++ request should be considered on a case-by-case basis.
++
++ Note that if the transform value includes 90 or 270 degree rotation,
++ the width of the buffer will become the surface height and the height
++ of the buffer will become the surface width.
++
++ If transform is not one of the values from the
++ wl_output.transform enum the invalid_transform protocol error
++ is raised.
++ </description>
++ <arg name="transform" type="int" enum="wl_output.transform"
++ summary="transform for interpreting buffer contents"/>
++ </request>
++
++ <!-- Version 3 additions -->
++
++ <request name="set_buffer_scale" since="3">
++ <description summary="sets the buffer scaling factor">
++ This request sets an optional scaling factor on how the compositor
++ interprets the contents of the buffer attached to the window.
++
++ Buffer scale is double-buffered state, see wl_surface.commit.
++
++ A newly created surface has its buffer scale set to 1.
++
++ wl_surface.set_buffer_scale changes the pending buffer scale.
++ wl_surface.commit copies the pending buffer scale to the current one.
++ Otherwise, the pending and current values are never changed.
++
++ The purpose of this request is to allow clients to supply higher
++ resolution buffer data for use on high resolution outputs. It is
++ intended that you pick the same buffer scale as the scale of the
++ output that the surface is displayed on. This means the compositor
++ can avoid scaling when rendering the surface on that output.
++
++ Note that if the scale is larger than 1, then you have to attach
++ a buffer that is larger (by a factor of scale in each dimension)
++ than the desired surface size.
++
++ If scale is not positive the invalid_scale protocol error is
++ raised.
++ </description>
++ <arg name="scale" type="int"
++ summary="positive scale for interpreting buffer contents"/>
++ </request>
++
++ <!-- Version 4 additions -->
++ <request name="damage_buffer" since="4">
++ <description summary="mark part of the surface damaged using buffer coordinates">
++ This request is used to describe the regions where the pending
++ buffer is different from the current surface contents, and where
++ the surface therefore needs to be repainted. The compositor
++ ignores the parts of the damage that fall outside of the surface.
++
++ Damage is double-buffered state, see wl_surface.commit.
++
++ The damage rectangle is specified in buffer coordinates,
++ where x and y specify the upper left corner of the damage rectangle.
++
++ The initial value for pending damage is empty: no damage.
++ wl_surface.damage_buffer adds pending damage: the new pending
++ damage is the union of old pending damage and the given rectangle.
++
++ wl_surface.commit assigns pending damage as the current damage,
++ and clears pending damage. The server will clear the current
++ damage as it repaints the surface.
++
++ This request differs from wl_surface.damage in only one way - it
++ takes damage in buffer coordinates instead of surface-local
++ coordinates. While this generally is more intuitive than surface
++ coordinates, it is especially desirable when using wp_viewport
++ or when a drawing library (like EGL) is unaware of buffer scale
++ and buffer transform.
++
++ Note: Because buffer transformation changes and damage requests may
++ be interleaved in the protocol stream, it is impossible to determine
++ the actual mapping between surface and buffer damage until
++ wl_surface.commit time. Therefore, compositors wishing to take both
++ kinds of damage into account will have to accumulate damage from the
++ two requests separately and only transform from one to the other
++ after receiving the wl_surface.commit.
++ </description>
++ <arg name="x" type="int" summary="buffer-local x coordinate"/>
++ <arg name="y" type="int" summary="buffer-local y coordinate"/>
++ <arg name="width" type="int" summary="width of damage rectangle"/>
++ <arg name="height" type="int" summary="height of damage rectangle"/>
++ </request>
++ </interface>
++
++ <interface name="wl_seat" version="6">
++ <description summary="group of input devices">
++ A seat is a group of keyboards, pointer and touch devices. This
++ object is published as a global during start up, or when such a
++ device is hot plugged. A seat typically has a pointer and
++ maintains a keyboard focus and a pointer focus.
++ </description>
++
++ <enum name="capability" bitfield="true">
++ <description summary="seat capability bitmask">
++ This is a bitmask of capabilities this seat has; if a member is
++ set, then it is present on the seat.
++ </description>
++ <entry name="pointer" value="1" summary="the seat has pointer devices"/>
++ <entry name="keyboard" value="2" summary="the seat has one or more keyboards"/>
++ <entry name="touch" value="4" summary="the seat has touch devices"/>
++ </enum>
++
++ <event name="capabilities">
++ <description summary="seat capabilities changed">
++ This is emitted whenever a seat gains or loses the pointer,
++ keyboard or touch capabilities. The argument is a capability
++ enum containing the complete set of capabilities this seat has.
++
++ When the pointer capability is added, a client may create a
++ wl_pointer object using the wl_seat.get_pointer request. This object
++ will receive pointer events until the capability is removed in the
++ future.
++
++ When the pointer capability is removed, a client should destroy the
++ wl_pointer objects associated with the seat where the capability was
++ removed, using the wl_pointer.release request. No further pointer
++ events will be received on these objects.
++
++ In some compositors, if a seat regains the pointer capability and a
++ client has a previously obtained wl_pointer object of version 4 or
++ less, that object may start sending pointer events again. This
++ behavior is considered a misinterpretation of the intended behavior
++ and must not be relied upon by the client. wl_pointer objects of
++ version 5 or later must not send events if created before the most
++ recent event notifying the client of an added pointer capability.
++
++ The above behavior also applies to wl_keyboard and wl_touch with the
++ keyboard and touch capabilities, respectively.
++ </description>
++ <arg name="capabilities" type="uint" enum="capability" summary="capabilities of the seat"/>
++ </event>
++
++ <request name="get_pointer">
++ <description summary="return pointer object">
++ The ID provided will be initialized to the wl_pointer interface
++ for this seat.
++
++ This request only takes effect if the seat has the pointer
++ capability, or has had the pointer capability in the past.
++ It is a protocol violation to issue this request on a seat that has
++ never had the pointer capability.
++ </description>
++ <arg name="id" type="new_id" interface="wl_pointer" summary="seat pointer"/>
++ </request>
++
++ <request name="get_keyboard">
++ <description summary="return keyboard object">
++ The ID provided will be initialized to the wl_keyboard interface
++ for this seat.
++
++ This request only takes effect if the seat has the keyboard
++ capability, or has had the keyboard capability in the past.
++ It is a protocol violation to issue this request on a seat that has
++ never had the keyboard capability.
++ </description>
++ <arg name="id" type="new_id" interface="wl_keyboard" summary="seat keyboard"/>
++ </request>
++
++ <request name="get_touch">
++ <description summary="return touch object">
++ The ID provided will be initialized to the wl_touch interface
++ for this seat.
++
++ This request only takes effect if the seat has the touch
++ capability, or has had the touch capability in the past.
++ It is a protocol violation to issue this request on a seat that has
++ never had the touch capability.
++ </description>
++ <arg name="id" type="new_id" interface="wl_touch" summary="seat touch interface"/>
++ </request>
++
++ <!-- Version 2 additions -->
++
++ <event name="name" since="2">
++ <description summary="unique identifier for this seat">
++ In a multiseat configuration this can be used by the client to help
++ identify which physical devices the seat represents. Based on
++ the seat configuration used by the compositor.
++ </description>
++ <arg name="name" type="string" summary="seat identifier"/>
++ </event>
++
++ <!-- Version 5 additions -->
++
++ <request name="release" type="destructor" since="5">
++ <description summary="release the seat object">
++ Using this request a client can tell the server that it is not going to
++ use the seat object anymore.
++ </description>
++ </request>
++
++ </interface>
++
++ <interface name="wl_pointer" version="6">
++ <description summary="pointer input device">
++ The wl_pointer interface represents one or more input devices,
++ such as mice, which control the pointer location and pointer_focus
++ of a seat.
++
++ The wl_pointer interface generates motion, enter and leave
++ events for the surfaces that the pointer is located over,
++ and button and axis events for button presses, button releases
++ and scrolling.
++ </description>
++
++ <enum name="error">
++ <entry name="role" value="0" summary="given wl_surface has another role"/>
++ </enum>
++
++ <request name="set_cursor">
++ <description summary="set the pointer surface">
++ Set the pointer surface, i.e., the surface that contains the
++ pointer image (cursor). This request gives the surface the role
++ of a cursor. If the surface already has another role, it raises
++ a protocol error.
++
++ The cursor actually changes only if the pointer
++ focus for this device is one of the requesting client's surfaces
++ or the surface parameter is the current pointer surface. If
++ there was a previous surface set with this request it is
++ replaced. If surface is NULL, the pointer image is hidden.
++
++ The parameters hotspot_x and hotspot_y define the position of
++ the pointer surface relative to the pointer location. Its
++ top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
++ where (x, y) are the coordinates of the pointer location, in
++ surface-local coordinates.
++
++ On surface.attach requests to the pointer surface, hotspot_x
++ and hotspot_y are decremented by the x and y parameters
++ passed to the request. Attach must be confirmed by
++ wl_surface.commit as usual.
++
++ The hotspot can also be updated by passing the currently set
++ pointer surface to this request with new values for hotspot_x
++ and hotspot_y.
++
++ The current and pending input regions of the wl_surface are
++ cleared, and wl_surface.set_input_region is ignored until the
++ wl_surface is no longer used as the cursor. When the use as a
++ cursor ends, the current and pending input regions become
++ undefined, and the wl_surface is unmapped.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the enter event"/>
++ <arg name="surface" type="object" interface="wl_surface" allow-null="true"
++ summary="pointer surface"/>
++ <arg name="hotspot_x" type="int" summary="surface-local x coordinate"/>
++ <arg name="hotspot_y" type="int" summary="surface-local y coordinate"/>
++ </request>
++
++ <event name="enter">
++ <description summary="enter event">
++ Notification that this seat's pointer is focused on a certain
++ surface.
++
++ When a seat's focus enters a surface, the pointer image
++ is undefined and a client should respond to this event by setting
++ an appropriate pointer image with the set_cursor request.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the enter event"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="surface entered by the pointer"/>
++ <arg name="surface_x" type="fixed" summary="surface-local x coordinate"/>
++ <arg name="surface_y" type="fixed" summary="surface-local y coordinate"/>
++ </event>
++
++ <event name="leave">
++ <description summary="leave event">
++ Notification that this seat's pointer is no longer focused on
++ a certain surface.
++
++ The leave notification is sent before the enter notification
++ for the new focus.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the leave event"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="surface left by the pointer"/>
++ </event>
++
++ <event name="motion">
++ <description summary="pointer motion event">
++ Notification of pointer location change. The arguments
++ surface_x and surface_y are the location relative to the
++ focused surface.
++ </description>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="surface_x" type="fixed" summary="surface-local x coordinate"/>
++ <arg name="surface_y" type="fixed" summary="surface-local y coordinate"/>
++ </event>
++
++ <enum name="button_state">
++ <description summary="physical button state">
++ Describes the physical state of a button that produced the button
++ event.
++ </description>
++ <entry name="released" value="0" summary="the button is not pressed"/>
++ <entry name="pressed" value="1" summary="the button is pressed"/>
++ </enum>
++
++ <event name="button">
++ <description summary="pointer button event">
++ Mouse button click and release notifications.
++
++ The location of the click is given by the last motion or
++ enter event.
++ The time argument is a timestamp with millisecond
++ granularity, with an undefined base.
++
++ The button is a button code as defined in the Linux kernel's
++ linux/input-event-codes.h header file, e.g. BTN_LEFT.
++
++ Any 16-bit button code value is reserved for future additions to the
++ kernel's event code list. All other button codes above 0xFFFF are
++ currently undefined but may be used in future versions of this
++ protocol.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the button event"/>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="button" type="uint" summary="button that produced the event"/>
++ <arg name="state" type="uint" enum="button_state" summary="physical state of the button"/>
++ </event>
++
++ <enum name="axis">
++ <description summary="axis types">
++ Describes the axis types of scroll events.
++ </description>
++ <entry name="vertical_scroll" value="0" summary="vertical axis"/>
++ <entry name="horizontal_scroll" value="1" summary="horizontal axis"/>
++ </enum>
++
++ <event name="axis">
++ <description summary="axis event">
++ Scroll and other axis notifications.
++
++ For scroll events (vertical and horizontal scroll axes), the
++ value parameter is the length of a vector along the specified
++ axis in a coordinate space identical to those of motion events,
++ representing a relative movement along the specified axis.
++
++ For devices that support movements non-parallel to axes multiple
++ axis events will be emitted.
++
++ When applicable, for example for touch pads, the server can
++ choose to emit scroll events where the motion vector is
++ equivalent to a motion event vector.
++
++ When applicable, a client can transform its content relative to the
++ scroll distance.
++ </description>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="axis" type="uint" enum="axis" summary="axis type"/>
++ <arg name="value" type="fixed" summary="length of vector in surface-local coordinate space"/>
++ </event>
++
++ <!-- Version 3 additions -->
++
++ <request name="release" type="destructor" since="3">
++ <description summary="release the pointer object">
++ Using this request a client can tell the server that it is not going to
++ use the pointer object anymore.
++
++ This request destroys the pointer proxy object, so clients must not call
++ wl_pointer_destroy() after using this request.
++ </description>
++ </request>
++
++ <!-- Version 5 additions -->
++
++ <event name="frame" since="5">
++ <description summary="end of a pointer event sequence">
++ Indicates the end of a set of events that logically belong together.
++ A client is expected to accumulate the data in all events within the
++ frame before proceeding.
++
++ All wl_pointer events before a wl_pointer.frame event belong
++ logically together. For example, in a diagonal scroll motion the
++ compositor will send an optional wl_pointer.axis_source event, two
++ wl_pointer.axis events (horizontal and vertical) and finally a
++ wl_pointer.frame event. The client may use this information to
++ calculate a diagonal vector for scrolling.
++
++ When multiple wl_pointer.axis events occur within the same frame,
++ the motion vector is the combined motion of all events.
++ When a wl_pointer.axis and a wl_pointer.axis_stop event occur within
++ the same frame, this indicates that axis movement in one axis has
++ stopped but continues in the other axis.
++ When multiple wl_pointer.axis_stop events occur within the same
++ frame, this indicates that these axes stopped in the same instance.
++
++ A wl_pointer.frame event is sent for every logical event group,
++ even if the group only contains a single wl_pointer event.
++ Specifically, a client may get a sequence: motion, frame, button,
++ frame, axis, frame, axis_stop, frame.
++
++ The wl_pointer.enter and wl_pointer.leave events are logical events
++ generated by the compositor and not the hardware. These events are
++ also grouped by a wl_pointer.frame. When a pointer moves from one
++ surface to another, a compositor should group the
++ wl_pointer.leave event within the same wl_pointer.frame.
++ However, a client must not rely on wl_pointer.leave and
++ wl_pointer.enter being in the same wl_pointer.frame.
++ Compositor-specific policies may require the wl_pointer.leave and
++ wl_pointer.enter event being split across multiple wl_pointer.frame
++ groups.
++ </description>
++ </event>
++
++ <enum name="axis_source">
++ <description summary="axis source types">
++ Describes the source types for axis events. This indicates to the
++ client how an axis event was physically generated; a client may
++ adjust the user interface accordingly. For example, scroll events
++ from a "finger" source may be in a smooth coordinate space with
++ kinetic scrolling whereas a "wheel" source may be in discrete steps
++ of a number of lines.
++ </description>
++ <entry name="wheel" value="0" summary="a physical wheel rotation" />
++ <entry name="finger" value="1" summary="finger on a touch surface" />
++ <entry name="continuous" value="2">
++ <description summary="continuous coordinate space">
++ A device generating events in a continuous coordinate space, but
++ using something other than a finger. One example for this source
++ is button-based scrolling where the vertical motion of a device
++ is converted to scroll events while a button is held down.
++ </description>
++ </entry>
++ <entry name="wheel_tilt" value="3" since="6">
++ <description summary="a physical wheel tilt">
++ Indicates that the actual device is a wheel but the scroll event is
++ not caused by a rotation but a (usually sideways) tilt of the wheel.
++ </description>
++ </entry>
++ </enum>
++
++ <event name="axis_source" since="5">
++ <description summary="axis source event">
++ Source information for scroll and other axes.
++
++ This event does not occur on its own. It is sent before a
++ wl_pointer.frame event and carries the source information for
++ all events within that frame.
++
++ The source specifies how this event was generated. If the source is
++ wl_pointer.axis_source.finger, a wl_pointer.axis_stop event will be
++ sent when the user lifts the finger off the device.
++
++ If the source is wl_pointer.axis_source.wheel,
++ wl_pointer.axis_source.wheel_tilt or
++ wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event may
++ or may not be sent. Whether a compositor sends an axis_stop event
++ for these sources is hardware-specific and implementation-dependent;
++ clients must not rely on receiving an axis_stop event for these
++ scroll sources and should treat scroll sequences from these scroll
++ sources as unterminated by default.
++
++ This event is optional. If the source is unknown for a particular
++ axis event sequence, no event is sent.
++ Only one wl_pointer.axis_source event is permitted per frame.
++
++ The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
++ not guaranteed.
++ </description>
++ <arg name="axis_source" type="uint" enum="axis_source" summary="source of the axis event"/>
++ </event>
++
++ <event name="axis_stop" since="5">
++ <description summary="axis stop event">
++ Stop notification for scroll and other axes.
++
++ For some wl_pointer.axis_source types, a wl_pointer.axis_stop event
++ is sent to notify a client that the axis sequence has terminated.
++ This enables the client to implement kinetic scrolling.
++ See the wl_pointer.axis_source documentation for information on when
++ this event may be generated.
++
++ Any wl_pointer.axis events with the same axis_source after this
++ event should be considered as the start of a new axis motion.
++
++ The timestamp is to be interpreted identical to the timestamp in the
++ wl_pointer.axis event. The timestamp value may be the same as a
++ preceding wl_pointer.axis event.
++ </description>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="axis" type="uint" enum="axis" summary="the axis stopped with this event"/>
++ </event>
++
++ <event name="axis_discrete" since="5">
++ <description summary="axis click event">
++ Discrete step information for scroll and other axes.
++
++ This event carries the axis value of the wl_pointer.axis event in
++ discrete steps (e.g. mouse wheel clicks).
++
++ This event does not occur on its own, it is coupled with a
++ wl_pointer.axis event that represents this axis value on a
++ continuous scale. The protocol guarantees that each axis_discrete
++ event is always followed by exactly one axis event with the same
++ axis number within the same wl_pointer.frame. Note that the protocol
++ allows for other events to occur between the axis_discrete and
++ its coupled axis event, including other axis_discrete or axis
++ events.
++
++ This event is optional; continuous scrolling devices
++ like two-finger scrolling on touchpads do not have discrete
++ steps and do not generate this event.
++
++ The discrete value carries the directional information. e.g. a value
++ of -2 is two steps towards the negative direction of this axis.
++
++ The axis number is identical to the axis number in the associated
++ axis event.
++
++ The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
++ not guaranteed.
++ </description>
++ <arg name="axis" type="uint" enum="axis" summary="axis type"/>
++ <arg name="discrete" type="int" summary="number of steps"/>
++ </event>
++ </interface>
++
++ <interface name="wl_keyboard" version="6">
++ <description summary="keyboard input device">
++ The wl_keyboard interface represents one or more keyboards
++ associated with a seat.
++ </description>
++
++ <enum name="keymap_format">
++ <description summary="keyboard mapping format">
++ This specifies the format of the keymap provided to the
++ client with the wl_keyboard.keymap event.
++ </description>
++ <entry name="no_keymap" value="0"
++ summary="no keymap; client must understand how to interpret the raw keycode"/>
++ <entry name="xkb_v1" value="1"
++ summary="libxkbcommon compatible; to determine the xkb keycode, clients must add 8 to the key event keycode"/>
++ </enum>
++
++ <event name="keymap">
++ <description summary="keyboard mapping">
++ This event provides a file descriptor to the client which can be
++ memory-mapped to provide a keyboard mapping description.
++ </description>
++ <arg name="format" type="uint" enum="keymap_format" summary="keymap format"/>
++ <arg name="fd" type="fd" summary="keymap file descriptor"/>
++ <arg name="size" type="uint" summary="keymap size, in bytes"/>
++ </event>
++
++ <event name="enter">
++ <description summary="enter event">
++ Notification that this seat's keyboard focus is on a certain
++ surface.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the enter event"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="surface gaining keyboard focus"/>
++ <arg name="keys" type="array" summary="the currently pressed keys"/>
++ </event>
++
++ <event name="leave">
++ <description summary="leave event">
++ Notification that this seat's keyboard focus is no longer on
++ a certain surface.
++
++ The leave notification is sent before the enter notification
++ for the new focus.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the leave event"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="surface that lost keyboard focus"/>
++ </event>
++
++ <enum name="key_state">
++ <description summary="physical key state">
++ Describes the physical state of a key that produced the key event.
++ </description>
++ <entry name="released" value="0" summary="key is not pressed"/>
++ <entry name="pressed" value="1" summary="key is pressed"/>
++ </enum>
++
++ <event name="key">
++ <description summary="key event">
++ A key was pressed or released.
++ The time argument is a timestamp with millisecond
++ granularity, with an undefined base.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the key event"/>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="key" type="uint" summary="key that produced the event"/>
++ <arg name="state" type="uint" enum="key_state" summary="physical state of the key"/>
++ </event>
++
++ <event name="modifiers">
++ <description summary="modifier and group state">
++ Notifies clients that the modifier and/or group state has
++ changed, and it should update its local state.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the modifiers event"/>
++ <arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
++ <arg name="mods_latched" type="uint" summary="latched modifiers"/>
++ <arg name="mods_locked" type="uint" summary="locked modifiers"/>
++ <arg name="group" type="uint" summary="keyboard layout"/>
++ </event>
++
++ <!-- Version 3 additions -->
++
++ <request name="release" type="destructor" since="3">
++ <description summary="release the keyboard object"/>
++ </request>
++
++ <!-- Version 4 additions -->
++
++ <event name="repeat_info" since="4">
++ <description summary="repeat rate and delay">
++ Informs the client about the keyboard's repeat rate and delay.
++
++ This event is sent as soon as the wl_keyboard object has been created,
++ and is guaranteed to be received by the client before any key press
++ event.
++
++ Negative values for either rate or delay are illegal. A rate of zero
++ will disable any repeating (regardless of the value of delay).
++
++ This event can be sent later on as well with a new value if necessary,
++ so clients should continue listening for the event past the creation
++ of wl_keyboard.
++ </description>
++ <arg name="rate" type="int"
++ summary="the rate of repeating keys in characters per second"/>
++ <arg name="delay" type="int"
++ summary="delay in milliseconds since key down until repeating starts"/>
++ </event>
++ </interface>
++
++ <interface name="wl_touch" version="6">
++ <description summary="touchscreen input device">
++ The wl_touch interface represents a touchscreen
++ associated with a seat.
++
++ Touch interactions can consist of one or more contacts.
++ For each contact, a series of events is generated, starting
++ with a down event, followed by zero or more motion events,
++ and ending with an up event. Events relating to the same
++ contact point can be identified by the ID of the sequence.
++ </description>
++
++ <event name="down">
++ <description summary="touch down event and beginning of a touch sequence">
++ A new touch point has appeared on the surface. This touch point is
++ assigned a unique ID. Future events from this touch point reference
++ this ID. The ID ceases to be valid after a touch up event and may be
++ reused in the future.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the touch down event"/>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="surface" type="object" interface="wl_surface" summary="surface touched"/>
++ <arg name="id" type="int" summary="the unique ID of this touch point"/>
++ <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++ <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++ </event>
++
++ <event name="up">
++ <description summary="end of a touch event sequence">
++ The touch point has disappeared. No further events will be sent for
++ this touch point and the touch point's ID is released and may be
++ reused in a future touch down event.
++ </description>
++ <arg name="serial" type="uint" summary="serial number of the touch up event"/>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="id" type="int" summary="the unique ID of this touch point"/>
++ </event>
++
++ <event name="motion">
++ <description summary="update of touch point coordinates">
++ A touch point has changed coordinates.
++ </description>
++ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++ <arg name="id" type="int" summary="the unique ID of this touch point"/>
++ <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++ <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++ </event>
++
++ <event name="frame">
++ <description summary="end of touch frame event">
++ Indicates the end of a set of events that logically belong together.
++ A client is expected to accumulate the data in all events within the
++ frame before proceeding.
++
++ A wl_touch.frame terminates at least one event but otherwise no
++ guarantee is provided about the set of events within a frame. A client
++ must assume that any state not updated in a frame is unchanged from the
++ previously known state.
++ </description>
++ </event>
++
++ <event name="cancel">
++ <description summary="touch session cancelled">
++ Sent if the compositor decides the touch stream is a global
++ gesture. No further events are sent to the clients from that
++ particular gesture. Touch cancellation applies to all touch points
++ currently active on this client's surface. The client is
++ responsible for finalizing the touch points, future touch points on
++ this surface may reuse the touch point ID.
++ </description>
++ </event>
++
++ <!-- Version 3 additions -->
++
++ <request name="release" type="destructor" since="3">
++ <description summary="release the touch object"/>
++ </request>
++
++ <!-- Version 6 additions -->
++
++ <event name="shape" since="6">
++ <description summary="update shape of touch point">
++ Sent when a touchpoint has changed its shape.
++
++ This event does not occur on its own. It is sent before a
++ wl_touch.frame event and carries the new shape information for
++ any previously reported, or new touch points of that frame.
++
++ Other events describing the touch point such as wl_touch.down,
++ wl_touch.motion or wl_touch.orientation may be sent within the
++ same wl_touch.frame. A client should treat these events as a single
++ logical touch point update. The order of wl_touch.shape,
++ wl_touch.orientation and wl_touch.motion is not guaranteed.
++ A wl_touch.down event is guaranteed to occur before the first
++ wl_touch.shape event for this touch ID but both events may occur within
++ the same wl_touch.frame.
++
++ A touchpoint shape is approximated by an ellipse through the major and
++ minor axis length. The major axis length describes the longer diameter
++ of the ellipse, while the minor axis length describes the shorter
++ diameter. Major and minor are orthogonal and both are specified in
++ surface-local coordinates. The center of the ellipse is always at the
++ touchpoint location as reported by wl_touch.down or wl_touch.move.
++
++ This event is only sent by the compositor if the touch device supports
++ shape reports. The client has to make reasonable assumptions about the
++ shape if it did not receive this event.
++ </description>
++ <arg name="id" type="int" summary="the unique ID of this touch point"/>
++ <arg name="major" type="fixed" summary="length of the major axis in surface-local coordinates"/>
++ <arg name="minor" type="fixed" summary="length of the minor axis in surface-local coordinates"/>
++ </event>
++
++ <event name="orientation" since="6">
++ <description summary="update orientation of touch point">
++ Sent when a touchpoint has changed its orientation.
++
++ This event does not occur on its own. It is sent before a
++ wl_touch.frame event and carries the new shape information for
++ any previously reported, or new touch points of that frame.
++
++ Other events describing the touch point such as wl_touch.down,
++ wl_touch.motion or wl_touch.shape may be sent within the
++ same wl_touch.frame. A client should treat these events as a single
++ logical touch point update. The order of wl_touch.shape,
++ wl_touch.orientation and wl_touch.motion is not guaranteed.
++ A wl_touch.down event is guaranteed to occur before the first
++ wl_touch.orientation event for this touch ID but both events may occur
++ within the same wl_touch.frame.
++
++ The orientation describes the clockwise angle of a touchpoint's major
++ axis to the positive surface y-axis and is normalized to the -180 to
++ +180 degree range. The granularity of orientation depends on the touch
++ device, some devices only support binary rotation values between 0 and
++ 90 degrees.
++
++ This event is only sent by the compositor if the touch device supports
++ orientation reports.
++ </description>
++ <arg name="id" type="int" summary="the unique ID of this touch point"/>
++ <arg name="orientation" type="fixed" summary="angle between major axis and positive surface y-axis in degrees"/>
++ </event>
++ </interface>
++
++ <interface name="wl_output" version="3">
++ <description summary="compositor output region">
++ An output describes part of the compositor geometry. The
++ compositor works in the 'compositor coordinate system' and an
++ output corresponds to a rectangular area in that space that is
++ actually visible. This typically corresponds to a monitor that
++ displays part of the compositor space. This object is published
++ as global during start up, or when a monitor is hotplugged.
++ </description>
++
++ <enum name="subpixel">
++ <description summary="subpixel geometry information">
++ This enumeration describes how the physical
++ pixels on an output are laid out.
++ </description>
++ <entry name="unknown" value="0" summary="unknown geometry"/>
++ <entry name="none" value="1" summary="no geometry"/>
++ <entry name="horizontal_rgb" value="2" summary="horizontal RGB"/>
++ <entry name="horizontal_bgr" value="3" summary="horizontal BGR"/>
++ <entry name="vertical_rgb" value="4" summary="vertical RGB"/>
++ <entry name="vertical_bgr" value="5" summary="vertical BGR"/>
++ </enum>
++
++ <enum name="transform">
++ <description summary="transform from framebuffer to output">
++ This describes the transform that a compositor will apply to a
++ surface to compensate for the rotation or mirroring of an
++ output device.
++
++ The flipped values correspond to an initial flip around a
++ vertical axis followed by rotation.
++
++ The purpose is mainly to allow clients to render accordingly and
++ tell the compositor, so that for fullscreen surfaces, the
++ compositor will still be able to scan out directly from client
++ surfaces.
++ </description>
++ <entry name="normal" value="0" summary="no transform"/>
++ <entry name="90" value="1" summary="90 degrees counter-clockwise"/>
++ <entry name="180" value="2" summary="180 degrees counter-clockwise"/>
++ <entry name="270" value="3" summary="270 degrees counter-clockwise"/>
++ <entry name="flipped" value="4" summary="180 degree flip around a vertical axis"/>
++ <entry name="flipped_90" value="5" summary="flip and rotate 90 degrees counter-clockwise"/>
++ <entry name="flipped_180" value="6" summary="flip and rotate 180 degrees counter-clockwise"/>
++ <entry name="flipped_270" value="7" summary="flip and rotate 270 degrees counter-clockwise"/>
++ </enum>
++
++ <event name="geometry">
++ <description summary="properties of the output">
++ The geometry event describes geometric properties of the output.
++ The event is sent when binding to the output object and whenever
++ any of the properties change.
++ </description>
++ <arg name="x" type="int"
++ summary="x position within the global compositor space"/>
++ <arg name="y" type="int"
++ summary="y position within the global compositor space"/>
++ <arg name="physical_width" type="int"
++ summary="width in millimeters of the output"/>
++ <arg name="physical_height" type="int"
++ summary="height in millimeters of the output"/>
++ <arg name="subpixel" type="int" enum="subpixel"
++ summary="subpixel orientation of the output"/>
++ <arg name="make" type="string"
++ summary="textual description of the manufacturer"/>
++ <arg name="model" type="string"
++ summary="textual description of the model"/>
++ <arg name="transform" type="int" enum="transform"
++ summary="transform that maps framebuffer to output"/>
++ </event>
++
++ <enum name="mode" bitfield="true">
++ <description summary="mode information">
++ These flags describe properties of an output mode.
++ They are used in the flags bitfield of the mode event.
++ </description>
++ <entry name="current" value="0x1"
++ summary="indicates this is the current mode"/>
++ <entry name="preferred" value="0x2"
++ summary="indicates this is the preferred mode"/>
++ </enum>
++
++ <event name="mode">
++ <description summary="advertise available modes for the output">
++ The mode event describes an available mode for the output.
++
++ The event is sent when binding to the output object and there
++ will always be one mode, the current mode. The event is sent
++ again if an output changes mode, for the mode that is now
++ current. In other words, the current mode is always the last
++ mode that was received with the current flag set.
++
++ The size of a mode is given in physical hardware units of
++ the output device. This is not necessarily the same as
++ the output size in the global compositor space. For instance,
++ the output may be scaled, as described in wl_output.scale,
++ or transformed, as described in wl_output.transform.
++ </description>
++ <arg name="flags" type="uint" enum="mode" summary="bitfield of mode flags"/>
++ <arg name="width" type="int" summary="width of the mode in hardware units"/>
++ <arg name="height" type="int" summary="height of the mode in hardware units"/>
++ <arg name="refresh" type="int" summary="vertical refresh rate in mHz"/>
++ </event>
++
++ <!-- Version 2 additions -->
++
++ <event name="done" since="2">
++ <description summary="sent all information about output">
++ This event is sent after all other properties have been
++ sent after binding to the output object and after any
++ other property changes done after that. This allows
++ changes to the output properties to be seen as
++ atomic, even if they happen via multiple events.
++ </description>
++ </event>
++
++ <event name="scale" since="2">
++ <description summary="output scaling properties">
++ This event contains scaling geometry information
++ that is not in the geometry event. It may be sent after
++ binding the output object or if the output scale changes
++ later. If it is not sent, the client should assume a
++ scale of 1.
++
++ A scale larger than 1 means that the compositor will
++ automatically scale surface buffers by this amount
++ when rendering. This is used for very high resolution
++ displays where applications rendering at the native
++ resolution would be too small to be legible.
++
++ It is intended that scaling aware clients track the
++ current output of a surface, and if it is on a scaled
++ output it should use wl_surface.set_buffer_scale with
++ the scale of the output. That way the compositor can
++ avoid scaling the surface, and the client can supply
++ a higher detail image.
++ </description>
++ <arg name="factor" type="int" summary="scaling factor of output"/>
++ </event>
++
++ <!-- Version 3 additions -->
++
++ <request name="release" type="destructor" since="3">
++ <description summary="release the output object">
++ Using this request a client can tell the server that it is not going to
++ use the output object anymore.
++ </description>
++ </request>
++ </interface>
++
++ <interface name="wl_region" version="1">
++ <description summary="region interface">
++ A region object describes an area.
++
++ Region objects are used to describe the opaque and input
++ regions of a surface.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="destroy region">
++ Destroy the region. This will invalidate the object ID.
++ </description>
++ </request>
++
++ <request name="add">
++ <description summary="add rectangle to region">
++ Add the specified rectangle to the region.
++ </description>
++ <arg name="x" type="int" summary="region-local x coordinate"/>
++ <arg name="y" type="int" summary="region-local y coordinate"/>
++ <arg name="width" type="int" summary="rectangle width"/>
++ <arg name="height" type="int" summary="rectangle height"/>
++ </request>
++
++ <request name="subtract">
++ <description summary="subtract rectangle from region">
++ Subtract the specified rectangle from the region.
++ </description>
++ <arg name="x" type="int" summary="region-local x coordinate"/>
++ <arg name="y" type="int" summary="region-local y coordinate"/>
++ <arg name="width" type="int" summary="rectangle width"/>
++ <arg name="height" type="int" summary="rectangle height"/>
++ </request>
++ </interface>
++
++ <interface name="wl_subcompositor" version="1">
++ <description summary="sub-surface compositing">
++ The global interface exposing sub-surface compositing capabilities.
++ A wl_surface, that has sub-surfaces associated, is called the
++ parent surface. Sub-surfaces can be arbitrarily nested and create
++ a tree of sub-surfaces.
++
++ The root surface in a tree of sub-surfaces is the main
++ surface. The main surface cannot be a sub-surface, because
++ sub-surfaces must always have a parent.
++
++ A main surface with its sub-surfaces forms a (compound) window.
++ For window management purposes, this set of wl_surface objects is
++ to be considered as a single window, and it should also behave as
++ such.
++
++ The aim of sub-surfaces is to offload some of the compositing work
++ within a window from clients to the compositor. A prime example is
++ a video player with decorations and video in separate wl_surface
++ objects. This should allow the compositor to pass YUV video buffer
++ processing to dedicated overlay hardware when possible.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="unbind from the subcompositor interface">
++ Informs the server that the client will not be using this
++ protocol object anymore. This does not affect any other
++ objects, wl_subsurface objects included.
++ </description>
++ </request>
++
++ <enum name="error">
++ <entry name="bad_surface" value="0"
++ summary="the to-be sub-surface is invalid"/>
++ </enum>
++
++ <request name="get_subsurface">
++ <description summary="give a surface the role sub-surface">
++ Create a sub-surface interface for the given surface, and
++ associate it with the given parent surface. This turns a
++ plain wl_surface into a sub-surface.
++
++ The to-be sub-surface must not already have another role, and it
++ must not have an existing wl_subsurface object. Otherwise a protocol
++ error is raised.
++ </description>
++ <arg name="id" type="new_id" interface="wl_subsurface"
++ summary="the new sub-surface object ID"/>
++ <arg name="surface" type="object" interface="wl_surface"
++ summary="the surface to be turned into a sub-surface"/>
++ <arg name="parent" type="object" interface="wl_surface"
++ summary="the parent surface"/>
++ </request>
++ </interface>
++
++ <interface name="wl_subsurface" version="1">
++ <description summary="sub-surface interface to a wl_surface">
++ An additional interface to a wl_surface object, which has been
++ made a sub-surface. A sub-surface has one parent surface. A
++ sub-surface's size and position are not limited to that of the parent.
++ Particularly, a sub-surface is not automatically clipped to its
++ parent's area.
++
++ A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
++ and the parent surface is mapped. The order of which one happens
++ first is irrelevant. A sub-surface is hidden if the parent becomes
++ hidden, or if a NULL wl_buffer is applied. These rules apply
++ recursively through the tree of surfaces.
++
++ The behaviour of a wl_surface.commit request on a sub-surface
++ depends on the sub-surface's mode. The possible modes are
++ synchronized and desynchronized, see methods
++ wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
++ mode caches the wl_surface state to be applied when the parent's
++ state gets applied, and desynchronized mode applies the pending
++ wl_surface state directly. A sub-surface is initially in the
++ synchronized mode.
++
++ Sub-surfaces have also other kind of state, which is managed by
++ wl_subsurface requests, as opposed to wl_surface requests. This
++ state includes the sub-surface position relative to the parent
++ surface (wl_subsurface.set_position), and the stacking order of
++ the parent and its sub-surfaces (wl_subsurface.place_above and
++ .place_below). This state is applied when the parent surface's
++ wl_surface state is applied, regardless of the sub-surface's mode.
++ As the exception, set_sync and set_desync are effective immediately.
++
++ The main surface can be thought to be always in desynchronized mode,
++ since it does not have a parent in the sub-surfaces sense.
++
++ Even if a sub-surface is in desynchronized mode, it will behave as
++ in synchronized mode, if its parent surface behaves as in
++ synchronized mode. This rule is applied recursively throughout the
++ tree of surfaces. This means, that one can set a sub-surface into
++ synchronized mode, and then assume that all its child and grand-child
++ sub-surfaces are synchronized, too, without explicitly setting them.
++
++ If the wl_surface associated with the wl_subsurface is destroyed, the
++ wl_subsurface object becomes inert. Note, that destroying either object
++ takes effect immediately. If you need to synchronize the removal
++ of a sub-surface to the parent surface update, unmap the sub-surface
++ first by attaching a NULL wl_buffer, update parent, and then destroy
++ the sub-surface.
++
++ If the parent wl_surface object is destroyed, the sub-surface is
++ unmapped.
++ </description>
++
++ <request name="destroy" type="destructor">
++ <description summary="remove sub-surface interface">
++ The sub-surface interface is removed from the wl_surface object
++ that was turned into a sub-surface with a
++ wl_subcompositor.get_subsurface request. The wl_surface's association
++ to the parent is deleted, and the wl_surface loses its role as
++ a sub-surface. The wl_surface is unmapped.
++ </description>
++ </request>
++
++ <enum name="error">
++ <entry name="bad_surface" value="0"
++ summary="wl_surface is not a sibling or the parent"/>
++ </enum>
++
++ <request name="set_position">
++ <description summary="reposition the sub-surface">
++ This schedules a sub-surface position change.
++ The sub-surface will be moved so that its origin (top left
++ corner pixel) will be at the location x, y of the parent surface
++ coordinate system. The coordinates are not restricted to the parent
++ surface area. Negative values are allowed.
++
++ The scheduled coordinates will take effect whenever the state of the
++ parent surface is applied. When this happens depends on whether the
++ parent surface is in synchronized mode or not. See
++ wl_subsurface.set_sync and wl_subsurface.set_desync for details.
++
++ If more than one set_position request is invoked by the client before
++ the commit of the parent surface, the position of a new request always
++ replaces the scheduled position from any previous request.
++
++ The initial position is 0, 0.
++ </description>
++ <arg name="x" type="int" summary="x coordinate in the parent surface"/>
++ <arg name="y" type="int" summary="y coordinate in the parent surface"/>
++ </request>
++
++ <request name="place_above">
++ <description summary="restack the sub-surface">
++ This sub-surface is taken from the stack, and put back just
++ above the reference surface, changing the z-order of the sub-surfaces.
++ The reference surface must be one of the sibling surfaces, or the
++ parent surface. Using any other surface, including this sub-surface,
++ will cause a protocol error.
++
++ The z-order is double-buffered. Requests are handled in order and
++ applied immediately to a pending state. The final pending state is
++ copied to the active state the next time the state of the parent
++ surface is applied. When this happens depends on whether the parent
++ surface is in synchronized mode or not. See wl_subsurface.set_sync and
++ wl_subsurface.set_desync for details.
++
++ A new sub-surface is initially added as the top-most in the stack
++ of its siblings and parent.
++ </description>
++ <arg name="sibling" type="object" interface="wl_surface"
++ summary="the reference surface"/>
++ </request>
++
++ <request name="place_below">
++ <description summary="restack the sub-surface">
++ The sub-surface is placed just below the reference surface.
++ See wl_subsurface.place_above.
++ </description>
++ <arg name="sibling" type="object" interface="wl_surface"
++ summary="the reference surface"/>
++ </request>
++
++ <request name="set_sync">
++ <description summary="set sub-surface to synchronized mode">
++ Change the commit behaviour of the sub-surface to synchronized
++ mode, also described as the parent dependent mode.
++
++ In synchronized mode, wl_surface.commit on a sub-surface will
++ accumulate the committed state in a cache, but the state will
++ not be applied and hence will not change the compositor output.
++ The cached state is applied to the sub-surface immediately after
++ the parent surface's state is applied. This ensures atomic
++ updates of the parent and all its synchronized sub-surfaces.
++ Applying the cached state will invalidate the cache, so further
++ parent surface commits do not (re-)apply old state.
++
++ See wl_subsurface for the recursive effect of this mode.
++ </description>
++ </request>
++
++ <request name="set_desync">
++ <description summary="set sub-surface to desynchronized mode">
++ Change the commit behaviour of the sub-surface to desynchronized
++ mode, also described as independent or freely running mode.
++
++ In desynchronized mode, wl_surface.commit on a sub-surface will
++ apply the pending state directly, without caching, as happens
++ normally with a wl_surface. Calling wl_surface.commit on the
++ parent surface has no effect on the sub-surface's wl_surface
++ state. This mode allows a sub-surface to be updated on its own.
++
++ If cached state exists when wl_surface.commit is called in
++ desynchronized mode, the pending state is added to the cached
++ state, and applied as a whole. This invalidates the cache.
++
++ Note: even if a sub-surface is set to desynchronized, a parent
++ sub-surface may override it to behave as synchronized. For details,
++ see wl_subsurface.
++
++ If a surface's parent surface behaves as desynchronized, then
++ the cached state is applied on set_desync.
++ </description>
++ </request>
++ </interface>
++
++</protocol>
--- /dev/null
--- /dev/null
++/* SCANNER TEST */
++
++#ifndef SMALL_TEST_CLIENT_PROTOCOL_H
++#define SMALL_TEST_CLIENT_PROTOCOL_H
++
++#include <stdint.h>
++#include <stddef.h>
++#include "wayland-client-core.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * @page page_small_test The small_test protocol
++ * @section page_ifaces_small_test Interfaces
++ * - @subpage page_iface_intf_A - the thing A
++ * @section page_copyright_small_test Copyright
++ * <pre>
++ *
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ * </pre>
++ */
++struct another_intf;
++struct intf_A;
++struct intf_not_here;
++
++#ifndef INTF_A_INTERFACE
++#define INTF_A_INTERFACE
++/**
++ * @page page_iface_intf_A intf_A
++ * @section page_iface_intf_A_desc Description
++ *
++ * A useless example trying to tickle the scanner.
++ * @section page_iface_intf_A_api API
++ * See @ref iface_intf_A.
++ */
++/**
++ * @defgroup iface_intf_A The intf_A interface
++ *
++ * A useless example trying to tickle the scanner.
++ */
++extern const struct wl_interface intf_A_interface;
++#endif
++
++#ifndef INTF_A_FOO_ENUM
++#define INTF_A_FOO_ENUM
++enum intf_A_foo {
++ /**
++ * this is the first
++ */
++ INTF_A_FOO_FIRST = 0,
++ /**
++ * this is the second
++ */
++ INTF_A_FOO_SECOND = 1,
++ /**
++ * this is the third
++ * @since 2
++ */
++ INTF_A_FOO_THIRD = 2,
++};
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_FOO_THIRD_SINCE_VERSION 2
++#endif /* INTF_A_FOO_ENUM */
++
++/**
++ * @ingroup iface_intf_A
++ * @struct intf_A_listener
++ */
++struct intf_A_listener {
++ /**
++ */
++ void (*hey)(void *data,
++ struct intf_A *intf_A);
++};
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline int
++intf_A_add_listener(struct intf_A *intf_A,
++ const struct intf_A_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) intf_A,
++ (void (**)(void)) listener, data);
++}
++
++#define INTF_A_RQ1 0
++#define INTF_A_RQ2 1
++#define INTF_A_DESTROY 2
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_HEY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ1_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ2_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_DESTROY_SINCE_VERSION 1
++
++/** @ingroup iface_intf_A */
++static inline void
++intf_A_set_user_data(struct intf_A *intf_A, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) intf_A, user_data);
++}
++
++/** @ingroup iface_intf_A */
++static inline void *
++intf_A_get_user_data(struct intf_A *intf_A)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) intf_A);
++}
++
++static inline uint32_t
++intf_A_get_version(struct intf_A *intf_A)
++{
++ return wl_proxy_get_version((struct wl_proxy *) intf_A);
++}
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline void *
++intf_A_rq1(struct intf_A *intf_A, const struct wl_interface *interface, uint32_t version)
++{
++ struct wl_proxy *untyped_new;
++
++ untyped_new = wl_proxy_marshal_flags((struct wl_proxy *) intf_A,
++ INTF_A_RQ1, interface, version, 0, interface->name, version, NULL);
++
++ return (void *) untyped_new;
++}
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline struct intf_not_here *
++intf_A_rq2(struct intf_A *intf_A, const char *str, int32_t i, uint32_t u, wl_fixed_t f, int32_t fd, struct another_intf *obj)
++{
++ struct wl_proxy *typed_new;
++
++ typed_new = wl_proxy_marshal_flags((struct wl_proxy *) intf_A,
++ INTF_A_RQ2, &intf_not_here_interface, wl_proxy_get_version((struct wl_proxy *) intf_A), 0, NULL, str, i, u, f, fd, obj);
++
++ return (struct intf_not_here *) typed_new;
++}
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline void
++intf_A_destroy(struct intf_A *intf_A)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) intf_A,
++ INTF_A_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) intf_A), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
--- /dev/null
--- /dev/null
++/* SCANNER TEST */
++
++#ifndef SMALL_TEST_CLIENT_PROTOCOL_H
++#define SMALL_TEST_CLIENT_PROTOCOL_H
++
++#include <stdint.h>
++#include <stddef.h>
++#include "wayland-client.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * @page page_small_test The small_test protocol
++ * @section page_ifaces_small_test Interfaces
++ * - @subpage page_iface_intf_A - the thing A
++ * @section page_copyright_small_test Copyright
++ * <pre>
++ *
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ * </pre>
++ */
++struct another_intf;
++struct intf_A;
++struct intf_not_here;
++
++#ifndef INTF_A_INTERFACE
++#define INTF_A_INTERFACE
++/**
++ * @page page_iface_intf_A intf_A
++ * @section page_iface_intf_A_desc Description
++ *
++ * A useless example trying to tickle the scanner.
++ * @section page_iface_intf_A_api API
++ * See @ref iface_intf_A.
++ */
++/**
++ * @defgroup iface_intf_A The intf_A interface
++ *
++ * A useless example trying to tickle the scanner.
++ */
++extern const struct wl_interface intf_A_interface;
++#endif
++
++#ifndef INTF_A_FOO_ENUM
++#define INTF_A_FOO_ENUM
++enum intf_A_foo {
++ /**
++ * this is the first
++ */
++ INTF_A_FOO_FIRST = 0,
++ /**
++ * this is the second
++ */
++ INTF_A_FOO_SECOND = 1,
++ /**
++ * this is the third
++ * @since 2
++ */
++ INTF_A_FOO_THIRD = 2,
++};
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_FOO_THIRD_SINCE_VERSION 2
++#endif /* INTF_A_FOO_ENUM */
++
++/**
++ * @ingroup iface_intf_A
++ * @struct intf_A_listener
++ */
++struct intf_A_listener {
++ /**
++ */
++ void (*hey)(void *data,
++ struct intf_A *intf_A);
++};
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline int
++intf_A_add_listener(struct intf_A *intf_A,
++ const struct intf_A_listener *listener, void *data)
++{
++ return wl_proxy_add_listener((struct wl_proxy *) intf_A,
++ (void (**)(void)) listener, data);
++}
++
++#define INTF_A_RQ1 0
++#define INTF_A_RQ2 1
++#define INTF_A_DESTROY 2
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_HEY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ1_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ2_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_DESTROY_SINCE_VERSION 1
++
++/** @ingroup iface_intf_A */
++static inline void
++intf_A_set_user_data(struct intf_A *intf_A, void *user_data)
++{
++ wl_proxy_set_user_data((struct wl_proxy *) intf_A, user_data);
++}
++
++/** @ingroup iface_intf_A */
++static inline void *
++intf_A_get_user_data(struct intf_A *intf_A)
++{
++ return wl_proxy_get_user_data((struct wl_proxy *) intf_A);
++}
++
++static inline uint32_t
++intf_A_get_version(struct intf_A *intf_A)
++{
++ return wl_proxy_get_version((struct wl_proxy *) intf_A);
++}
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline void *
++intf_A_rq1(struct intf_A *intf_A, const struct wl_interface *interface, uint32_t version)
++{
++ struct wl_proxy *untyped_new;
++
++ untyped_new = wl_proxy_marshal_flags((struct wl_proxy *) intf_A,
++ INTF_A_RQ1, interface, version, 0, interface->name, version, NULL);
++
++ return (void *) untyped_new;
++}
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline struct intf_not_here *
++intf_A_rq2(struct intf_A *intf_A, const char *str, int32_t i, uint32_t u, wl_fixed_t f, int32_t fd, struct another_intf *obj)
++{
++ struct wl_proxy *typed_new;
++
++ typed_new = wl_proxy_marshal_flags((struct wl_proxy *) intf_A,
++ INTF_A_RQ2, &intf_not_here_interface, wl_proxy_get_version((struct wl_proxy *) intf_A), 0, NULL, str, i, u, f, fd, obj);
++
++ return (struct intf_not_here *) typed_new;
++}
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline void
++intf_A_destroy(struct intf_A *intf_A)
++{
++ wl_proxy_marshal_flags((struct wl_proxy *) intf_A,
++ INTF_A_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) intf_A), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
--- /dev/null
--- /dev/null
++/* SCANNER TEST */
++
++/*
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <stdint.h>
++#include "wayland-util.h"
++
++extern const struct wl_interface another_intf_interface;
++extern const struct wl_interface intf_not_here_interface;
++
++static const struct wl_interface *small_test_types[] = {
++ NULL,
++ &intf_not_here_interface,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ &another_intf_interface,
++};
++
++static const struct wl_message intf_A_requests[] = {
++ { "rq1", "sun", small_test_types + 0 },
++ { "rq2", "nsiufho", small_test_types + 1 },
++ { "destroy", "", small_test_types + 0 },
++};
++
++static const struct wl_message intf_A_events[] = {
++ { "hey", "", small_test_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface intf_A_interface = {
++ "intf_A", 3,
++ 3, intf_A_requests,
++ 1, intf_A_events,
++};
++
--- /dev/null
--- /dev/null
++/* SCANNER TEST */
++
++/*
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <stdint.h>
++#include "wayland-util.h"
++
++extern const struct wl_interface another_intf_interface;
++extern const struct wl_interface intf_not_here_interface;
++
++static const struct wl_interface *small_test_types[] = {
++ NULL,
++ &intf_not_here_interface,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ &another_intf_interface,
++};
++
++static const struct wl_message intf_A_requests[] = {
++ { "rq1", "sun", small_test_types + 0 },
++ { "rq2", "nsiufho", small_test_types + 1 },
++ { "destroy", "", small_test_types + 0 },
++};
++
++static const struct wl_message intf_A_events[] = {
++ { "hey", "", small_test_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface intf_A_interface = {
++ "intf_A", 3,
++ 3, intf_A_requests,
++ 1, intf_A_events,
++};
++
--- /dev/null
--- /dev/null
++/* SCANNER TEST */
++
++/*
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <stdint.h>
++#include "wayland-util.h"
++
++#ifndef __has_attribute
++# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
++#endif
++
++#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
++#define WL_PRIVATE __attribute__ ((visibility("hidden")))
++#else
++#define WL_PRIVATE
++#endif
++
++extern const struct wl_interface another_intf_interface;
++extern const struct wl_interface intf_not_here_interface;
++
++static const struct wl_interface *small_test_types[] = {
++ NULL,
++ &intf_not_here_interface,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ NULL,
++ &another_intf_interface,
++};
++
++static const struct wl_message intf_A_requests[] = {
++ { "rq1", "sun", small_test_types + 0 },
++ { "rq2", "nsiufho", small_test_types + 1 },
++ { "destroy", "", small_test_types + 0 },
++};
++
++static const struct wl_message intf_A_events[] = {
++ { "hey", "", small_test_types + 0 },
++};
++
++WL_PRIVATE const struct wl_interface intf_A_interface = {
++ "intf_A", 3,
++ 3, intf_A_requests,
++ 1, intf_A_events,
++};
++
--- /dev/null
--- /dev/null
++/* SCANNER TEST */
++
++#ifndef SMALL_TEST_SERVER_PROTOCOL_H
++#define SMALL_TEST_SERVER_PROTOCOL_H
++
++#include <stdint.h>
++#include <stddef.h>
++#include "wayland-server-core.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct wl_client;
++struct wl_resource;
++
++/**
++ * @page page_small_test The small_test protocol
++ * @section page_ifaces_small_test Interfaces
++ * - @subpage page_iface_intf_A - the thing A
++ * @section page_copyright_small_test Copyright
++ * <pre>
++ *
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ * </pre>
++ */
++struct another_intf;
++struct intf_A;
++struct intf_not_here;
++
++#ifndef INTF_A_INTERFACE
++#define INTF_A_INTERFACE
++/**
++ * @page page_iface_intf_A intf_A
++ * @section page_iface_intf_A_desc Description
++ *
++ * A useless example trying to tickle the scanner.
++ * @section page_iface_intf_A_api API
++ * See @ref iface_intf_A.
++ */
++/**
++ * @defgroup iface_intf_A The intf_A interface
++ *
++ * A useless example trying to tickle the scanner.
++ */
++extern const struct wl_interface intf_A_interface;
++#endif
++
++#ifndef INTF_A_FOO_ENUM
++#define INTF_A_FOO_ENUM
++enum intf_A_foo {
++ /**
++ * this is the first
++ */
++ INTF_A_FOO_FIRST = 0,
++ /**
++ * this is the second
++ */
++ INTF_A_FOO_SECOND = 1,
++ /**
++ * this is the third
++ * @since 2
++ */
++ INTF_A_FOO_THIRD = 2,
++};
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_FOO_THIRD_SINCE_VERSION 2
++#endif /* INTF_A_FOO_ENUM */
++
++/**
++ * @ingroup iface_intf_A
++ * @struct intf_A_interface
++ */
++struct intf_A_interface {
++ /**
++ * @param interface name of the objects interface
++ * @param version version of the objects interface
++ */
++ void (*rq1)(struct wl_client *client,
++ struct wl_resource *resource,
++ const char *interface, uint32_t version, uint32_t untyped_new);
++ /**
++ */
++ void (*rq2)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t typed_new,
++ const char *str,
++ int32_t i,
++ uint32_t u,
++ wl_fixed_t f,
++ int32_t fd,
++ struct wl_resource *obj);
++ /**
++ */
++ void (*destroy)(struct wl_client *client,
++ struct wl_resource *resource);
++};
++
++#define INTF_A_HEY 0
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_HEY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ1_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ2_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_DESTROY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_intf_A
++ * Sends an hey event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++intf_A_send_hey(struct wl_resource *resource_)
++{
++ wl_resource_post_event(resource_, INTF_A_HEY);
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
--- /dev/null
--- /dev/null
++/* SCANNER TEST */
++
++#ifndef SMALL_TEST_SERVER_PROTOCOL_H
++#define SMALL_TEST_SERVER_PROTOCOL_H
++
++#include <stdint.h>
++#include <stddef.h>
++#include "wayland-server.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct wl_client;
++struct wl_resource;
++
++/**
++ * @page page_small_test The small_test protocol
++ * @section page_ifaces_small_test Interfaces
++ * - @subpage page_iface_intf_A - the thing A
++ * @section page_copyright_small_test Copyright
++ * <pre>
++ *
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ * </pre>
++ */
++struct another_intf;
++struct intf_A;
++struct intf_not_here;
++
++#ifndef INTF_A_INTERFACE
++#define INTF_A_INTERFACE
++/**
++ * @page page_iface_intf_A intf_A
++ * @section page_iface_intf_A_desc Description
++ *
++ * A useless example trying to tickle the scanner.
++ * @section page_iface_intf_A_api API
++ * See @ref iface_intf_A.
++ */
++/**
++ * @defgroup iface_intf_A The intf_A interface
++ *
++ * A useless example trying to tickle the scanner.
++ */
++extern const struct wl_interface intf_A_interface;
++#endif
++
++#ifndef INTF_A_FOO_ENUM
++#define INTF_A_FOO_ENUM
++enum intf_A_foo {
++ /**
++ * this is the first
++ */
++ INTF_A_FOO_FIRST = 0,
++ /**
++ * this is the second
++ */
++ INTF_A_FOO_SECOND = 1,
++ /**
++ * this is the third
++ * @since 2
++ */
++ INTF_A_FOO_THIRD = 2,
++};
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_FOO_THIRD_SINCE_VERSION 2
++#endif /* INTF_A_FOO_ENUM */
++
++/**
++ * @ingroup iface_intf_A
++ * @struct intf_A_interface
++ */
++struct intf_A_interface {
++ /**
++ * @param interface name of the objects interface
++ * @param version version of the objects interface
++ */
++ void (*rq1)(struct wl_client *client,
++ struct wl_resource *resource,
++ const char *interface, uint32_t version, uint32_t untyped_new);
++ /**
++ */
++ void (*rq2)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t typed_new,
++ const char *str,
++ int32_t i,
++ uint32_t u,
++ wl_fixed_t f,
++ int32_t fd,
++ struct wl_resource *obj);
++ /**
++ */
++ void (*destroy)(struct wl_client *client,
++ struct wl_resource *resource);
++};
++
++#define INTF_A_HEY 0
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_HEY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ1_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ2_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_DESTROY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_intf_A
++ * Sends an hey event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++intf_A_send_hey(struct wl_resource *resource_)
++{
++ wl_resource_post_event(resource_, INTF_A_HEY);
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
--- /dev/null
--- /dev/null
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="small_test">
++
++ <copyright>
++ Copyright © 2016 Collabora, Ltd.
++
++ Permission is hereby granted, free of charge, to any person
++ obtaining a copy of this software and associated documentation files
++ (the "Software"), to deal in the Software without restriction,
++ including without limitation the rights to use, copy, modify, merge,
++ publish, distribute, sublicense, and/or sell copies of the Software,
++ and to permit persons to whom the Software is furnished to do so,
++ subject to the following conditions:
++
++ The above copyright notice and this permission notice (including the
++ next paragraph) shall be included in all copies or substantial
++ portions of the Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ SOFTWARE.
++ </copyright>
++
++ <interface name="intf_A" version="3">
++ <description summary="the thing A">
++ A useless example trying to tickle the scanner.
++ </description>
++
++ <request name="rq1">
++ <arg name="untyped_new" type="new_id"/>
++ </request>
++
++ <request name="rq2">
++ <arg name="typed_new" type="new_id" interface="intf_not_here"/>
++ <arg name="str" type="string"/>
++ <arg name="i" type="int"/>
++ <arg name="u" type="uint"/>
++ <arg name="f" type="fixed"/>
++ <arg name="fd" type="fd"/>
++ <arg name="obj" type="object" interface="another_intf"/>
++ </request>
++
++ <request name="destroy" type="destructor"/>
++
++ <event name="hey"/>
++
++ <enum name="foo">
++ <entry name="first" value="0" summary="this is the first"/>
++ <entry name="second" value="1" summary="this is the second"/>
++ <entry name="third" value="2" since="2" summary="this is the third"/>
++ </enum>
++ </interface>
++</protocol>
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Intel Corporation
++ * Copyright © 2013 Jason Ekstrand
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++#include <stdbool.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdarg.h>
++#include <stdint.h>
++#include <string.h>
++#include <assert.h>
++#include <sys/socket.h>
++#include <unistd.h>
++#include <errno.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <sys/mman.h>
++
++#include <pthread.h>
++#include <poll.h>
++
++#include "wayland-private.h"
++#include "wayland-server.h"
++#include "wayland-client.h"
++#include "test-runner.h"
++#include "test-compositor.h"
++
++#include "tests-server-protocol.h"
++#include "tests-client-protocol.h"
++
++struct display_destroy_listener {
++ struct wl_listener listener;
++ int done;
++};
++
++static void
++display_destroy_notify(struct wl_listener *l, void *data)
++{
++ struct display_destroy_listener *listener;
++
++ listener = wl_container_of(l, listener, listener);
++ listener->done = 1;
++}
++
++TEST(display_destroy_listener)
++{
++ struct wl_display *display;
++ struct display_destroy_listener a, b;
++
++ display = wl_display_create();
++ assert(display);
++
++ a.listener.notify = &display_destroy_notify;
++ a.done = 0;
++ wl_display_add_destroy_listener(display, &a.listener);
++
++ assert(wl_display_get_destroy_listener(display, display_destroy_notify) ==
++ &a.listener);
++
++ b.listener.notify = display_destroy_notify;
++ b.done = 0;
++ wl_display_add_destroy_listener(display, &b.listener);
++
++ wl_list_remove(&a.listener.link);
++
++ wl_display_destroy(display);
++
++ assert(!a.done);
++ assert(b.done);
++}
++
++/* Fake 'client' which does not use wl_display_connect, and thus leaves the
++ * file descriptor passed through WAYLAND_SOCKET intact. This should not
++ * trigger an assertion in the leak check. */
++static void
++empty_client(void)
++{
++ return;
++}
++
++TEST(tc_leaks_tests)
++{
++ struct display *d = display_create();
++ client_create_noarg(d, empty_client);
++ display_run(d);
++ display_destroy(d);
++}
++
++/* This is how pre proxy-version registry binds worked,
++ * this should create a proxy that shares the display's
++ * version number: 0 */
++static void *
++old_registry_bind(struct wl_registry *wl_registry,
++ uint32_t name,
++ const struct wl_interface *interface,
++ uint32_t version)
++{
++ struct wl_proxy *id;
++
++ id = wl_proxy_marshal_constructor(
++ (struct wl_proxy *) wl_registry, WL_REGISTRY_BIND,
++ interface, name, interface->name, version, NULL);
++
++ return (void *) id;
++}
++
++struct handler_info {
++ struct wl_seat *seat;
++ uint32_t bind_version;
++ bool use_unversioned;
++};
++
++static void
++registry_handle_globals(void *data, struct wl_registry *registry,
++ uint32_t id, const char *intf, uint32_t ver)
++{
++ struct handler_info *hi = data;
++
++ /* This is only for the proxy version test */
++ if (hi->bind_version)
++ ver = hi->bind_version;
++
++ if (strcmp(intf, "wl_seat") == 0) {
++ if (hi->use_unversioned)
++ hi->seat = old_registry_bind(registry, id,
++ &wl_seat_interface, ver);
++ else
++ hi->seat = wl_registry_bind(registry, id,
++ &wl_seat_interface, ver);
++ assert(hi->seat);
++ }
++}
++
++static const struct wl_registry_listener registry_listener = {
++ registry_handle_globals,
++ NULL
++};
++
++static struct wl_seat *
++client_get_seat_with_info(struct client *c, struct handler_info *hi)
++{
++ struct wl_registry *reg = wl_display_get_registry(c->wl_display);
++ assert(reg);
++
++ assert(hi);
++ hi->seat = NULL;
++ wl_registry_add_listener(reg, ®istry_listener, hi);
++ wl_display_roundtrip(c->wl_display);
++ assert(hi->seat);
++
++ wl_registry_destroy(reg);
++
++ return hi->seat;
++}
++
++static struct wl_seat *
++client_get_seat(struct client *c)
++{
++ struct handler_info hi;
++
++ hi.use_unversioned = false;
++ hi.bind_version = 0;
++
++ return client_get_seat_with_info(c, &hi);
++}
++
++static void
++check_pending_error(struct client *c, struct wl_proxy *proxy)
++{
++ uint32_t ec, id;
++ int err;
++ const struct wl_interface *intf;
++
++ err = wl_display_get_error(c->wl_display);
++ assert(err == EPROTO);
++
++ ec = wl_display_get_protocol_error(c->wl_display, &intf, &id);
++ assert(ec == 23);
++ assert(intf == &wl_seat_interface);
++ assert(id == wl_proxy_get_id(proxy));
++}
++
++static void
++check_for_error(struct client *c, struct wl_proxy *proxy)
++{
++ /* client should be disconnected */
++ assert(wl_display_roundtrip(c->wl_display) == -1);
++
++ check_pending_error(c, proxy);
++}
++
++static struct client_info *
++find_client_info(struct display *d, struct wl_client *client)
++{
++ struct client_info *ci;
++
++ wl_list_for_each(ci, &d->clients, link) {
++ if (ci->wl_client == client)
++ return ci;
++ }
++
++ return NULL;
++}
++
++static void
++bind_seat(struct wl_client *client, void *data,
++ uint32_t vers, uint32_t id)
++{
++ struct display *d = data;
++ struct client_info *ci;
++ struct wl_resource *res;
++
++ ci = find_client_info(d, client);
++ assert(ci);
++
++ res = wl_resource_create(client, &wl_seat_interface, vers, id);
++ assert(res);
++
++ /* save the resource as client's info data,
++ * so that we can use it later */
++ ci->data = res;
++}
++
++static void
++client_disconnect_nocheck(struct client *c)
++{
++ wl_proxy_destroy((struct wl_proxy *) c->tc);
++ wl_display_disconnect(c->wl_display);
++ free(c);
++}
++
++static void
++post_error_main(void)
++{
++ struct client *c = client_connect();
++ struct wl_seat *seat = client_get_seat(c);
++
++ /* stop display so that it can post the error.
++ * The function should return -1, because of the posted error */
++ assert(stop_display(c, 1) == -1);
++
++ /* display should have posted error, check it! */
++ check_for_error(c, (struct wl_proxy *) seat);
++
++ /* don't call client_disconnect(c), because then the test would be
++ * aborted due to checks for error in this function */
++ wl_proxy_destroy((struct wl_proxy *) seat);
++ client_disconnect_nocheck(c);
++}
++
++TEST(post_error_to_one_client)
++{
++ struct display *d = display_create();
++ struct client_info *cl;
++
++ wl_global_create(d->wl_display, &wl_seat_interface,
++ 1, d, bind_seat);
++
++ cl = client_create_noarg(d, post_error_main);
++ display_run(d);
++
++ /* the display was stopped by client, so it can
++ * proceed in the code and post an error */
++ assert(cl->data);
++ wl_resource_post_error((struct wl_resource *) cl->data,
++ 23, "Dummy error");
++
++ /* this one should be ignored */
++ wl_resource_post_error((struct wl_resource *) cl->data,
++ 21, "Dummy error (ignore)");
++
++ display_resume(d);
++ display_destroy(d);
++}
++
++static void
++post_error_main2(void)
++{
++ struct client *c = client_connect();
++ struct wl_seat *seat = client_get_seat(c);
++
++ /* the error should not be posted for this client */
++ assert(stop_display(c, 2) >= 0);
++
++ wl_proxy_destroy((struct wl_proxy *) seat);
++ client_disconnect(c);
++}
++
++static void
++post_error_main3(void)
++{
++ struct client *c = client_connect();
++ struct wl_seat *seat = client_get_seat(c);
++
++ assert(stop_display(c, 2) == -1);
++ check_for_error(c, (struct wl_proxy *) seat);
++
++ /* don't call client_disconnect(c), because then the test would be
++ * aborted due to checks for error in this function */
++ wl_proxy_destroy((struct wl_proxy *) seat);
++ client_disconnect_nocheck(c);
++}
++
++/* all the testcases could be in one TEST, but splitting it
++ * apart is better for debugging when the test fails */
++TEST(post_error_to_one_from_two_clients)
++{
++ struct display *d = display_create();
++ struct client_info *cl;
++
++ wl_global_create(d->wl_display, &wl_seat_interface,
++ 1, d, bind_seat);
++
++ client_create_noarg(d, post_error_main2);
++ cl = client_create_noarg(d, post_error_main3);
++ display_run(d);
++
++ /* post error only to the second client */
++ assert(cl->data);
++ wl_resource_post_error((struct wl_resource *) cl->data,
++ 23, "Dummy error");
++ wl_resource_post_error((struct wl_resource *) cl->data,
++ 21, "Dummy error (ignore)");
++
++ display_resume(d);
++ display_destroy(d);
++}
++
++/* all the testcases could be in one TEST, but splitting it
++ * apart is better for debugging when the test fails */
++TEST(post_error_to_two_clients)
++{
++ struct display *d = display_create();
++ struct client_info *cl, *cl2;
++
++ wl_global_create(d->wl_display, &wl_seat_interface,
++ 1, d, bind_seat);
++
++ cl = client_create_noarg(d, post_error_main3);
++ cl2 = client_create_noarg(d, post_error_main3);
++
++ display_run(d);
++
++ /* Try to send the error to both clients */
++ assert(cl->data && cl2->data);
++ wl_resource_post_error((struct wl_resource *) cl->data,
++ 23, "Dummy error");
++ wl_resource_post_error((struct wl_resource *) cl->data,
++ 21, "Dummy error (ignore)");
++
++ wl_resource_post_error((struct wl_resource *) cl2->data,
++ 23, "Dummy error");
++ wl_resource_post_error((struct wl_resource *) cl2->data,
++ 21, "Dummy error (ignore)");
++
++ display_resume(d);
++ display_destroy(d);
++}
++
++static void
++post_nomem_main(void)
++{
++ struct client *c = client_connect();
++ struct wl_seat *seat = client_get_seat(c);
++
++ assert(stop_display(c, 1) == -1);
++ assert(wl_display_get_error(c->wl_display) == ENOMEM);
++
++ wl_proxy_destroy((struct wl_proxy *) seat);
++ client_disconnect_nocheck(c);
++}
++
++TEST(post_nomem_tst)
++{
++ struct display *d = display_create();
++ struct client_info *cl;
++
++ wl_global_create(d->wl_display, &wl_seat_interface,
++ 1, d, bind_seat);
++
++ cl = client_create_noarg(d, post_nomem_main);
++ display_run(d);
++
++ assert(cl->data);
++ wl_resource_post_no_memory((struct wl_resource *) cl->data);
++ display_resume(d);
++
++ /* first client terminated. Run it again,
++ * but post no memory to client */
++ cl = client_create_noarg(d, post_nomem_main);
++ display_run(d);
++
++ assert(cl->data);
++ wl_client_post_no_memory(cl->wl_client);
++ display_resume(d);
++
++ display_destroy(d);
++}
++
++static void
++post_implementation_error_main(void)
++{
++ struct client *c = client_connect();
++ struct wl_seat *seat = client_get_seat(c);
++ uint32_t object_id, protocol_error;
++ const struct wl_interface *interface;
++
++ assert(stop_display(c, 1) == -1);
++ int err = wl_display_get_error(c->wl_display);
++ fprintf(stderr, "Err is %i\n", err);
++ assert(err == EPROTO);
++ protocol_error = wl_display_get_protocol_error(c->wl_display,
++ &interface,
++ &object_id);
++ assert(protocol_error == WL_DISPLAY_ERROR_IMPLEMENTATION);
++ assert(interface == &wl_display_interface);
++
++ wl_proxy_destroy((struct wl_proxy *) seat);
++ client_disconnect_nocheck(c);
++}
++
++TEST(post_internal_error_tst)
++{
++ struct display *d = display_create();
++ struct client_info *cl;
++
++ wl_global_create(d->wl_display, &wl_seat_interface,
++ 1, d, bind_seat);
++
++ cl = client_create_noarg(d, post_implementation_error_main);
++ display_run(d);
++
++ wl_client_post_implementation_error(cl->wl_client, "Error %i", 20);
++
++ display_resume(d);
++
++ display_destroy(d);
++}
++
++static void
++register_reading(struct wl_display *display)
++{
++ while(wl_display_prepare_read(display) != 0 && errno == EAGAIN)
++ assert(wl_display_dispatch_pending(display) >= 0);
++ assert(wl_display_flush(display) >= 0);
++}
++
++/* create thread that will call prepare+read so that
++ * it will block */
++static pthread_t
++create_thread(struct client *c, void *(*func)(void*))
++{
++ pthread_t thread;
++
++ c->display_stopped = 0;
++ /* func must set display->stopped to 1 before sleeping */
++ assert(pthread_create(&thread, NULL, func, c) == 0);
++
++ /* make sure the thread is sleeping. It's a little bit racy
++ * (setting display_stopped to 1 and calling wl_display_read_events)
++ * so call usleep once again after the loop ends - it should
++ * be sufficient... */
++ while (c->display_stopped == 0)
++ test_usleep(500);
++ test_usleep(10000);
++
++ return thread;
++}
++
++static void *
++thread_read_error(void *data)
++{
++ struct client *c = data;
++
++ register_reading(c->wl_display);
++
++ /*
++ * Calling the read right now will block this thread
++ * until the other thread will read the data.
++ * However, after invoking an error, this
++ * thread should be woken up or it will block indefinitely.
++ */
++ c->display_stopped = 1;
++ assert(wl_display_read_events(c->wl_display) == -1);
++
++ assert(wl_display_dispatch_pending(c->wl_display) == -1);
++ assert(wl_display_get_error(c->wl_display));
++
++ pthread_exit(NULL);
++}
++
++/* test posting an error in multi-threaded environment. */
++static void
++threading_post_err(void)
++{
++ DISABLE_LEAK_CHECKS;
++
++ struct client *c = client_connect();
++ pthread_t thread;
++
++ /* register read intention */
++ register_reading(c->wl_display);
++
++ /* use this var as an indicator that thread is sleeping */
++ c->display_stopped = 0;
++
++ /* create new thread that will register its intention too */
++ thread = create_thread(c, thread_read_error);
++
++ /* so now we have sleeping thread waiting for a pthread_cond signal.
++ * The main thread must call wl_display_read_events().
++ * If this call fails, then it won't call broadcast at the
++ * end of the function and the sleeping thread will block indefinitely.
++ * Make the call fail and watch if libwayland will unblock the thread! */
++
++ /* create error on fd, so that wl_display_read_events will fail.
++ * The same can happen when server hangs up */
++ close(wl_display_get_fd(c->wl_display));
++ /* this read events will fail and will
++ * post an error that should wake the sleeping thread
++ * and dispatch the incoming events */
++ assert(wl_display_read_events(c->wl_display) == -1);
++
++ /* kill test in 3 seconds. This should be enough time for the
++ * thread to exit if it's not blocking. If everything is OK, than
++ * the thread was woken up and the test will end before the SIGALRM */
++ test_set_timeout(3);
++ pthread_join(thread, NULL);
++
++ client_disconnect_nocheck(c);
++}
++
++TEST(threading_errors_tst)
++{
++ struct display *d = display_create();
++
++ client_create_noarg(d, threading_post_err);
++ display_run(d);
++
++ display_destroy(d);
++}
++
++static void *
++thread_prepare_and_read(void *data)
++{
++ struct client *c = data;
++
++ register_reading(c->wl_display);
++
++ c->display_stopped = 1;
++
++ assert(wl_display_read_events(c->wl_display) == 0);
++ assert(wl_display_dispatch_pending(c->wl_display) == 0);
++
++ pthread_exit(NULL);
++}
++
++/* test cancel read*/
++static void
++threading_cancel_read(void)
++{
++ DISABLE_LEAK_CHECKS;
++
++ struct client *c = client_connect();
++ pthread_t th1, th2, th3;
++
++ register_reading(c->wl_display);
++
++ th1 = create_thread(c, thread_prepare_and_read);
++ th2 = create_thread(c, thread_prepare_and_read);
++ th3 = create_thread(c, thread_prepare_and_read);
++
++ /* all the threads are sleeping, waiting until read or cancel
++ * is called. Cancel the read and let the threads proceed */
++ wl_display_cancel_read(c->wl_display);
++
++ /* kill test in 3 seconds. This should be enough time for the
++ * thread to exit if it's not blocking. If everything is OK, than
++ * the thread was woken up and the test will end before the SIGALRM */
++ test_set_timeout(3);
++ pthread_join(th1, NULL);
++ pthread_join(th2, NULL);
++ pthread_join(th3, NULL);
++
++ client_disconnect(c);
++}
++
++TEST(threading_cancel_read_tst)
++{
++ struct display *d = display_create();
++
++ client_create_noarg(d, threading_cancel_read);
++ display_run(d);
++
++ display_destroy(d);
++}
++
++static void
++threading_read_eagain(void)
++{
++ DISABLE_LEAK_CHECKS;
++
++ struct client *c = client_connect();
++ pthread_t th1, th2, th3;
++
++ register_reading(c->wl_display);
++
++ th1 = create_thread(c, thread_prepare_and_read);
++ th2 = create_thread(c, thread_prepare_and_read);
++ th3 = create_thread(c, thread_prepare_and_read);
++
++ /* All the threads are sleeping, waiting until read or cancel
++ * is called. Since we have no data on socket waiting,
++ * the wl_connection_read should end up with error and set errno
++ * to EAGAIN. Check if the threads are woken up in this case. */
++ assert(wl_display_read_events(c->wl_display) == 0);
++ /* errno should be still set to EAGAIN if wl_connection_read
++ * set it - check if we're testing the right case */
++ assert(errno == EAGAIN);
++
++ test_set_timeout(3);
++ pthread_join(th1, NULL);
++ pthread_join(th2, NULL);
++ pthread_join(th3, NULL);
++
++ client_disconnect(c);
++}
++
++TEST(threading_read_eagain_tst)
++{
++ struct display *d = display_create();
++ client_create_noarg(d, threading_read_eagain);
++
++ display_run(d);
++
++ display_destroy(d);
++}
++
++static void *
++thread_prepare_and_read2(void *data)
++{
++ struct client *c = data;
++
++ while(wl_display_prepare_read(c->wl_display) != 0 && errno == EAGAIN)
++ assert(wl_display_dispatch_pending(c->wl_display) == -1);
++ assert(wl_display_flush(c->wl_display) == -1);
++
++ c->display_stopped = 1;
++
++ assert(wl_display_read_events(c->wl_display) == -1);
++ assert(wl_display_dispatch_pending(c->wl_display) == -1);
++
++ pthread_exit(NULL);
++}
++
++static void
++threading_read_after_error(void)
++{
++ DISABLE_LEAK_CHECKS;
++
++ struct client *c = client_connect();
++ pthread_t thread;
++
++ /* create an error */
++ close(wl_display_get_fd(c->wl_display));
++ assert(wl_display_dispatch(c->wl_display) == -1);
++
++ /* try to prepare for reading */
++ while(wl_display_prepare_read(c->wl_display) != 0 && errno == EAGAIN)
++ assert(wl_display_dispatch_pending(c->wl_display) == -1);
++ assert(wl_display_flush(c->wl_display) == -1);
++
++ assert(pthread_create(&thread, NULL,
++ thread_prepare_and_read2, c) == 0);
++
++ /* make sure thread is sleeping */
++ while (c->display_stopped == 0)
++ test_usleep(500);
++ test_usleep(10000);
++
++ assert(wl_display_read_events(c->wl_display) == -1);
++
++ /* kill test in 3 seconds */
++ test_set_timeout(3);
++ pthread_join(thread, NULL);
++
++ client_disconnect_nocheck(c);
++}
++
++TEST(threading_read_after_error_tst)
++{
++ struct display *d = display_create();
++
++ client_create_noarg(d, threading_read_after_error);
++ display_run(d);
++
++ display_destroy(d);
++}
++
++static void
++wait_for_error_using_dispatch(struct client *c, struct wl_proxy *proxy)
++{
++ int ret;
++
++ while (true) {
++ /* Dispatching should eventually hit the protocol error before
++ * any other error. */
++ ret = wl_display_dispatch(c->wl_display);
++ if (ret == 0) {
++ continue;
++ } else {
++ assert(errno == EPROTO);
++ break;
++ }
++ }
++
++ check_pending_error(c, proxy);
++}
++
++static void
++wait_for_error_using_prepare_read(struct client *c, struct wl_proxy *proxy)
++{
++ int ret = 0;
++ struct pollfd pfd[2];
++
++ while (true) {
++ while (wl_display_prepare_read(c->wl_display) != 0 &&
++ errno == EAGAIN) {
++ assert(wl_display_dispatch_pending(c->wl_display) >= 0);
++ }
++
++ /* Flush may fail due to EPIPE if the connection is broken, but
++ * this must not set a fatal display error because that would
++ * result in it being impossible to read a potential protocol
++ * error. */
++ do {
++ ret = wl_display_flush(c->wl_display);
++ } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
++ assert(ret >= 0 || errno == EPIPE);
++ assert(wl_display_get_error(c->wl_display) == 0);
++
++ pfd[0].fd = wl_display_get_fd(c->wl_display);
++ pfd[0].events = POLLIN;
++ do {
++ ret = poll(pfd, 1, -1);
++ } while (ret == -1 && errno == EINTR);
++ assert(ret != -1);
++
++ /* We should always manage to read the error before the EPIPE
++ * comes this way. */
++ assert(wl_display_read_events(c->wl_display) == 0);
++
++ /* Dispatching should eventually hit the protocol error before
++ * any other error. */
++ ret = wl_display_dispatch_pending(c->wl_display);
++ if (ret == 0) {
++ continue;
++ } else {
++ assert(errno == EPROTO);
++ break;
++ }
++ }
++
++ check_pending_error(c, proxy);
++}
++
++static void
++check_error_after_epipe(void *data)
++{
++ bool use_dispatch_helpers = *(bool *) data;
++ struct client *client;
++ struct wl_seat *seat;
++ struct wl_callback *callback;
++
++ client = client_connect();
++
++ /* This will, according to the implementation below, cause the server
++ * to post an error. */
++ seat = client_get_seat(client);
++ wl_display_flush(client->wl_display);
++
++ /* The server will not actually destroy the client until it receives
++ * input, so send something to trigger the client destruction. */
++ callback = wl_display_sync(client->wl_display);
++ wl_callback_destroy(callback);
++
++ /* Sleep some to give the server a chance to react and destroy the
++ * client. */
++ test_usleep(200000);
++
++ /* Wait for the protocol error and check that we reached it before
++ * EPIPE. */
++ if (use_dispatch_helpers) {
++ wait_for_error_using_dispatch(client, (struct wl_proxy *) seat);
++ } else {
++ wait_for_error_using_prepare_read(client,
++ (struct wl_proxy *) seat);
++ }
++
++ wl_seat_destroy(seat);
++ client_disconnect_nocheck(client);
++}
++
++static void
++bind_seat_and_post_error(struct wl_client *client, void *data,
++ uint32_t version, uint32_t id)
++{
++ struct display *d = data;
++ struct client_info *ci;
++ struct wl_resource *resource;
++
++ ci = find_client_info(d, client);
++ assert(ci);
++
++ resource = wl_resource_create(client, &wl_seat_interface, version, id);
++ assert(resource);
++ ci->data = resource;
++
++ wl_resource_post_error(ci->data, 23, "Dummy error");
++}
++
++TEST(error_code_after_epipe)
++{
++ struct display *d = display_create();
++ bool use_dispatch_helpers;
++
++ wl_global_create(d->wl_display, &wl_seat_interface,
++ 1, d, bind_seat_and_post_error);
++
++ use_dispatch_helpers = true;
++ client_create(d, check_error_after_epipe, &use_dispatch_helpers);
++ display_run(d);
++
++ use_dispatch_helpers = false;
++ client_create(d, check_error_after_epipe, &use_dispatch_helpers);
++ display_run(d);
++
++ display_destroy(d);
++}
++
++static void
++check_seat_versions(struct wl_seat *seat, uint32_t ev)
++{
++ struct wl_pointer *pointer;
++
++ assert(wl_proxy_get_version((struct wl_proxy *) seat) == ev);
++ assert(wl_seat_get_version(seat) == ev);
++
++ pointer = wl_seat_get_pointer(seat);
++ assert(wl_pointer_get_version(pointer) == ev);
++ assert(wl_proxy_get_version((struct wl_proxy *) pointer) == ev);
++ wl_proxy_destroy((struct wl_proxy *) pointer);
++}
++
++/* Normal client with proxy versions available. */
++static void
++seat_version(void *data)
++{
++ struct handler_info *hi = data;
++ struct client *c = client_connect();
++ struct wl_seat *seat;
++
++ /* display proxy should always be version 0 */
++ assert(wl_proxy_get_version((struct wl_proxy *) c->wl_display) == 0);
++
++ seat = client_get_seat_with_info(c, hi);
++ if (hi->use_unversioned)
++ check_seat_versions(seat, 0);
++ else
++ check_seat_versions(seat, hi->bind_version);
++
++ wl_proxy_destroy((struct wl_proxy *) seat);
++
++ client_disconnect_nocheck(c);
++}
++
++TEST(versions)
++{
++ struct display *d = display_create();
++ struct wl_global *global;
++ int i;
++
++ global = wl_global_create(d->wl_display, &wl_seat_interface,
++ 5, d, bind_seat);
++
++ for (i = 1; i <= 5; i++) {
++ struct handler_info hi;
++
++ hi.bind_version = i;
++ hi.use_unversioned = false;
++ client_create(d, seat_version, &hi);
++ hi.use_unversioned = true;
++ client_create(d, seat_version, &hi);
++ }
++
++ display_run(d);
++
++ wl_global_destroy(global);
++
++ display_destroy(d);
++}
++
++static void
++check_error_on_destroyed_object(void *data)
++{
++ struct client *c;
++ struct wl_seat *seat;
++ uint32_t id;
++ const struct wl_interface *intf;
++
++ c = client_connect();
++ seat = client_get_seat(c);
++
++ /* destroy the seat proxy. The display won't know
++ * about it yet, so it will post the error as usual */
++ wl_proxy_destroy((struct wl_proxy *) seat);
++
++ /* let display post the error. The error will
++ * be caught in stop_display while dispatching */
++ assert(stop_display(c, 1) == -1);
++
++ /* check the returned error. Since the object was destroyed,
++ * we don't know the interface and id */
++ assert(wl_display_get_error(c->wl_display) == EPROTO);
++ assert(wl_display_get_protocol_error(c->wl_display, &intf, &id) == 23);
++ assert(intf == NULL);
++ assert(id == 0);
++
++ client_disconnect_nocheck(c);
++}
++
++TEST(error_on_destroyed_object)
++{
++ struct client_info *cl;
++ struct display *d = display_create();
++
++ wl_global_create(d->wl_display, &wl_seat_interface,
++ 1, d, bind_seat);
++
++ cl = client_create_noarg(d, check_error_on_destroyed_object);
++ display_run(d);
++
++ /* did client bind to the seat? */
++ assert(cl->data);
++
++ /* post error on the destroyed object */
++ wl_resource_post_error((struct wl_resource *) cl->data,
++ 23, "Dummy error");
++ display_resume(d);
++ display_destroy(d);
++}
++
++static bool
++global_filter(const struct wl_client *client,
++ const struct wl_global *global,
++ void *data)
++{
++ /* Hide the wl_data_offer interface if no data was provided */
++ if (wl_global_get_interface(global) == &wl_data_offer_interface)
++ return data != NULL;
++
++ /* Show all the others */
++ return true;
++}
++
++static void
++bind_data_offer(struct wl_client *client, void *data,
++ uint32_t vers, uint32_t id)
++{
++ /* Client should not be able to bind to this interface! */
++ assert(false);
++}
++
++static void
++registry_handle_filtered(void *data, struct wl_registry *registry,
++ uint32_t id, const char *intf, uint32_t ver)
++{
++ uint32_t *name = data;
++
++ if (strcmp (intf, "wl_data_offer") == 0) {
++ assert(name);
++ *name = id;
++ }
++}
++
++static void
++registry_handle_remove_filtered(void *data, struct wl_registry *registry,
++ uint32_t id)
++{
++ assert(false);
++}
++
++static const struct wl_registry_listener registry_listener_filtered = {
++ registry_handle_filtered,
++ registry_handle_remove_filtered,
++};
++
++static void
++get_globals(void *data)
++{
++ struct client *c = client_connect();
++ struct wl_registry *registry;
++
++ registry = wl_display_get_registry(c->wl_display);
++ wl_registry_add_listener(registry, ®istry_listener_filtered, data);
++ wl_display_roundtrip(c->wl_display);
++
++ wl_registry_destroy(registry);
++ client_disconnect_nocheck(c);
++}
++
++TEST(filtered_global_is_hidden)
++{
++ struct display *d;
++ struct wl_global *g;
++
++ d = display_create();
++
++ g = wl_global_create(d->wl_display, &wl_data_offer_interface,
++ 1, d, bind_data_offer);
++ wl_display_set_global_filter(d->wl_display, global_filter, NULL);
++
++ client_create_noarg(d, get_globals);
++ display_run(d);
++
++ wl_global_destroy(g);
++
++ display_destroy(d);
++}
++
++static void
++get_dynamic_globals(void *data)
++{
++ struct client *c = client_connect();
++ struct wl_registry *registry;
++
++ registry = wl_display_get_registry(c->wl_display);
++ wl_registry_add_listener(registry, ®istry_listener_filtered, data);
++ wl_display_roundtrip(c->wl_display);
++
++ /* Wait for the server to create a new global */
++ assert(stop_display(c, 1) >= 0);
++
++ /* Check that we don't see it */
++ wl_display_roundtrip(c->wl_display);
++
++ /* Wait for the server to remove that global */
++ assert(stop_display(c, 1) >= 0);
++
++ /* Check that we don't get a global_remove event */
++ wl_display_roundtrip(c->wl_display);
++
++ wl_registry_destroy(registry);
++ client_disconnect_nocheck(c);
++}
++
++TEST(filtered_dynamic_global_is_hidden)
++{
++ struct display *d;
++ struct wl_global *g;
++
++ d = display_create();
++ wl_display_set_global_filter(d->wl_display, global_filter, NULL);
++
++ /* Create a client and let it enumerate the globals */
++ client_create_noarg(d, get_dynamic_globals);
++ display_run(d);
++
++ /* Dynamically create a new global */
++ g = wl_global_create(d->wl_display, &wl_data_offer_interface,
++ 1, d, bind_data_offer);
++
++ display_resume(d);
++
++ /* Dynamically remove the global */
++ wl_global_destroy(g);
++
++ display_resume(d);
++
++ display_destroy(d);
++}
++
++static void
++check_bind_error(struct client *c)
++{
++ uint32_t errorcode, id;
++ int err;
++ const struct wl_interface *intf;
++
++ err = wl_display_get_error(c->wl_display);
++ assert(err == EPROTO);
++
++ errorcode = wl_display_get_protocol_error(c->wl_display, &intf, &id);
++ assert(errorcode == WL_DISPLAY_ERROR_INVALID_OBJECT);
++}
++
++static void
++force_bind(void *data)
++{
++ struct client *c = client_connect();
++ struct wl_registry *registry;
++ void *ptr;
++ uint32_t *name = data;
++
++ registry = wl_display_get_registry(c->wl_display);
++
++ ptr = wl_registry_bind (registry, *name, &wl_data_offer_interface, 1);
++ wl_display_roundtrip(c->wl_display);
++ check_bind_error(c);
++
++ wl_proxy_destroy((struct wl_proxy *) ptr);
++ wl_registry_destroy(registry);
++
++ client_disconnect_nocheck(c);
++}
++
++TEST(bind_fails_on_filtered_global)
++{
++ struct display *d;
++ struct wl_global *g;
++ uint32_t *name;
++
++ /* Create a anonymous shared memory to pass the interface name */
++ name = mmap(NULL, sizeof(uint32_t),
++ PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
++
++ d = display_create();
++
++ g = wl_global_create(d->wl_display, &wl_data_offer_interface,
++ 1, d, bind_data_offer);
++ wl_display_set_global_filter(d->wl_display, global_filter, name);
++
++ client_create(d, get_globals, name);
++ *name = 0;
++
++ display_run(d);
++ /* wl_data_offer should be 2 */
++ assert(*name == 2);
++ wl_display_set_global_filter(d->wl_display, global_filter, NULL);
++
++ /* Try to bind to the interface name when a global filter is in place */
++ client_create(d, force_bind, name);
++ display_run(d);
++
++ wl_global_destroy(g);
++
++ display_destroy(d);
++}
++
++static void
++pre_fd(void *data, struct fd_passer *fdp)
++{
++ fd_passer_destroy(fdp);
++}
++
++static void
++fd(void *data, struct fd_passer *fdp, int32_t fd)
++{
++ /* We destroyed the resource before this event */
++ assert(false);
++}
++
++struct fd_passer_listener fd_passer_listener = {
++ pre_fd,
++ fd,
++};
++
++static void
++zombie_fd_handle_globals(void *data, struct wl_registry *registry,
++ uint32_t id, const char *intf, uint32_t ver)
++{
++ struct fd_passer *fdp;
++
++ if (!strcmp(intf, "fd_passer")) {
++ fdp = wl_registry_bind(registry, id, &fd_passer_interface, 1);
++ fd_passer_add_listener(fdp, &fd_passer_listener, NULL);
++ }
++}
++
++static const struct wl_registry_listener zombie_fd_registry_listener = {
++ zombie_fd_handle_globals,
++ NULL
++};
++
++static void
++zombie_client(void *data)
++{
++ struct client *c = client_connect();
++ struct wl_registry *registry;
++
++ registry = wl_display_get_registry(c->wl_display);
++ wl_registry_add_listener(registry, &zombie_fd_registry_listener, NULL);
++
++ /* Gets the registry */
++ wl_display_roundtrip(c->wl_display);
++
++ /* push out the fd_passer bind */
++ wl_display_roundtrip(c->wl_display);
++
++ /* push out our fd_passer.destroy */
++ wl_display_roundtrip(c->wl_display);
++
++ wl_registry_destroy(registry);
++
++ client_disconnect_nocheck(c);
++}
++
++struct passer_data {
++ struct wl_resource *conjoined_passer;
++};
++
++static void
++feed_pipe(int fd, char tosend)
++{
++ int count;
++
++ do {
++ count = write(fd, &tosend, 1);
++ } while (count != 1 && errno == EAGAIN);
++ assert(count == 1);
++ close(fd);
++}
++
++static void
++fd_passer_clobber(struct wl_client *client, struct wl_resource *res)
++{
++ struct passer_data *pdata = wl_resource_get_user_data(res);
++ int pipes1[2], pipes2[2], ret;
++
++ if (pdata->conjoined_passer) {
++ ret = pipe(pipes1);
++ assert(ret == 0);
++ ret = pipe(pipes2);
++ assert(ret == 0);
++
++ wl_resource_queue_event(res, FD_PASSER_FD, pipes1[0]);
++ fd_passer_send_fd(pdata->conjoined_passer, pipes2[0]);
++ feed_pipe(pipes1[1], '1');
++ feed_pipe(pipes2[1], '2');
++ close(pipes1[0]);
++ close(pipes2[0]);
++ }
++ wl_resource_destroy(res);
++}
++
++static void
++fd_passer_twin(struct wl_client *client, struct wl_resource *res, struct wl_resource *passer)
++{
++ struct passer_data *pdata = wl_resource_get_user_data(res);
++
++ pdata->conjoined_passer = passer;
++}
++
++static const struct fd_passer_interface fdp_interface = {
++ fd_passer_clobber,
++ fd_passer_twin
++};
++
++static void
++pdata_destroy(struct wl_resource *res)
++{
++ struct passer_data *pdata = wl_resource_get_user_data(res);
++
++ free(pdata);
++}
++
++static void
++bind_fd_passer(struct wl_client *client, void *data,
++ uint32_t vers, uint32_t id)
++{
++ struct wl_resource *res;
++ struct passer_data *pdata;
++
++ pdata = malloc(sizeof(*pdata));
++ assert(pdata);
++ pdata->conjoined_passer = NULL;
++
++ res = wl_resource_create(client, &fd_passer_interface, vers, id);
++ wl_resource_set_implementation(res, &fdp_interface, pdata, pdata_destroy);
++ assert(res);
++ if (vers == 1) {
++ fd_passer_send_pre_fd(res);
++ fd_passer_send_fd(res, fileno(stdin));
++ }
++}
++
++TEST(zombie_fd)
++{
++ struct display *d;
++ struct wl_global *g;
++
++ d = display_create();
++
++ g = wl_global_create(d->wl_display, &fd_passer_interface,
++ 1, d, bind_fd_passer);
++
++ client_create_noarg(d, zombie_client);
++ display_run(d);
++
++ wl_global_destroy(g);
++
++ display_destroy(d);
++}
++
++
++static void
++double_pre_fd(void *data, struct fd_passer *fdp)
++{
++ assert(false);
++}
++
++static void
++double_fd(void *data, struct fd_passer *fdp, int32_t fd)
++{
++ char buf;
++ int count;
++
++ do {
++ count = read(fd, &buf, 1);
++ } while (count != 1 && errno == EAGAIN);
++ assert(count == 1);
++
++ close(fd);
++ fd_passer_destroy(fdp);
++ assert(buf == '2');
++}
++
++struct fd_passer_listener double_fd_passer_listener = {
++ double_pre_fd,
++ double_fd,
++};
++
++
++static void
++double_zombie_fd_handle_globals(void *data, struct wl_registry *registry,
++ uint32_t id, const char *intf, uint32_t ver)
++{
++ struct fd_passer *fdp1, *fdp2;
++
++ if (!strcmp(intf, "fd_passer")) {
++ fdp1 = wl_registry_bind(registry, id, &fd_passer_interface, 2);
++ fd_passer_add_listener(fdp1, &double_fd_passer_listener, NULL);
++ fdp2 = wl_registry_bind(registry, id, &fd_passer_interface, 2);
++ fd_passer_add_listener(fdp2, &double_fd_passer_listener, NULL);
++ fd_passer_conjoin(fdp1, fdp2);
++ fd_passer_destroy(fdp1);
++ }
++}
++
++static const struct wl_registry_listener double_zombie_fd_registry_listener = {
++ double_zombie_fd_handle_globals,
++ NULL
++};
++
++static void
++double_zombie_client(void *data)
++{
++ struct client *c = client_connect();
++ struct wl_registry *registry;
++
++ registry = wl_display_get_registry(c->wl_display);
++ wl_registry_add_listener(registry, &double_zombie_fd_registry_listener, NULL);
++
++ /* Gets the registry */
++ wl_display_roundtrip(c->wl_display);
++
++ /* One more so server can respond to conjoin+destroy */
++ wl_display_roundtrip(c->wl_display);
++
++ /* And finally push out our last fd_passer.destroy */
++ wl_display_roundtrip(c->wl_display);
++
++ wl_registry_destroy(registry);
++
++ client_disconnect_nocheck(c);
++}
++
++TEST(zombie_fd_errant_consumption)
++{
++ struct display *d;
++ struct wl_global *g;
++
++ d = display_create();
++
++ g = wl_global_create(d->wl_display, &fd_passer_interface,
++ 2, d, bind_fd_passer);
++
++ client_create_noarg(d, double_zombie_client);
++ display_run(d);
++
++ wl_global_destroy(g);
++
++ display_destroy(d);
++}
++
++
++static void
++registry_bind_interface_mismatch_handle_global(void *data,
++ struct wl_registry *registry,
++ uint32_t id, const char *intf,
++ uint32_t ver)
++{
++ uint32_t *seat_id_ptr = data;
++
++ if (strcmp(intf, wl_seat_interface.name) == 0) {
++ *seat_id_ptr = id;
++ }
++}
++
++static const struct wl_registry_listener bind_interface_mismatch_registry_listener = {
++ registry_bind_interface_mismatch_handle_global,
++ NULL
++};
++
++static void
++registry_bind_interface_mismatch_client(void *data)
++{
++ struct client *c = client_connect();
++ struct wl_registry *registry;
++ uint32_t seat_id = 0;
++ void *ptr;
++ int ret;
++
++ registry = wl_display_get_registry(c->wl_display);
++ wl_registry_add_listener(registry,
++ &bind_interface_mismatch_registry_listener,
++ &seat_id);
++
++ ret = wl_display_roundtrip(c->wl_display);
++ assert(ret >= 0);
++ assert(seat_id != 0);
++
++ /* Bind with a different interface */
++ ptr = wl_registry_bind(registry, seat_id, &wl_output_interface, 1);
++ ret = wl_display_roundtrip(c->wl_display);
++ assert(ret < 0);
++ check_bind_error(c);
++
++ wl_proxy_destroy((struct wl_proxy *) ptr);
++ wl_registry_destroy(registry);
++
++ client_disconnect_nocheck(c);
++}
++
++TEST(registry_bind_interface_mismatch)
++{
++ struct display *d;
++ struct wl_global *seat_global;
++
++ d = display_create();
++
++ seat_global = wl_global_create(d->wl_display, &wl_seat_interface,
++ 1, NULL, NULL);
++
++ client_create_noarg(d, registry_bind_interface_mismatch_client);
++ display_run(d);
++
++ wl_global_destroy(seat_global);
++
++ display_destroy(d);
++}
++
++static void
++send_overflow_client(void *data)
++{
++ struct client *c = client_connect();
++ int i, err = 0;
++ int *pipes = data;
++ char tmp = '\0';
++ int sock, optval = 16384;
++
++ /* Limit the send buffer size for the display socket to guarantee
++ * that the test will cause an overflow. */
++ sock = wl_display_get_fd(c->wl_display);
++ assert(setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval)) == 0);
++
++ /* Request to break out of 'display_run' in the main process */
++ assert(stop_display(c, 1) >= 0);
++
++ /* On Linux, the actual socket data + metadata space is twice `optval`;
++ * since each noop request requires 8 bytes, the buffer should overflow
++ * within <=4096 iterations. */
++ for (i = 0; i < 1000000; i++) {
++ noop_request(c);
++ err = wl_display_get_error(c->wl_display);
++ if (err)
++ break;
++ }
++
++ /* Do not close the pipe file descriptors afterwards, because the leak
++ * check verifies that the initial/final FD counts are the same */
++ assert(write(pipes[1], &tmp, sizeof(tmp)) == (ssize_t)sizeof(tmp));
++
++ /* Expect an error */
++ fprintf(stderr, "Send loop failed on try %d, err = %d, %s\n", i, err, strerror(err));
++ assert(err == EAGAIN);
++
++ client_disconnect_nocheck(c);
++}
++
++TEST(send_overflow_disconnection)
++{
++ struct display *d;
++ char tmp;
++ int rpipe[2];
++ ssize_t ret;
++
++ assert(pipe(rpipe) != -1);
++
++ d = display_create();
++
++ (void) client_create(d, send_overflow_client, &rpipe);
++
++ /* Close write end of the pipe, so that the later read() call gets
++ * interrupted if the client dies */
++ close(rpipe[1]);
++
++ /* Run the display until the client sends a `stop_display`, then
++ * send a resume message but don't actually look at new messages */
++ display_run(d);
++ display_post_resume_events(d);
++ wl_display_flush_clients(d->wl_display);
++
++ /* Wait until all noop requests have been sent (read returns 1), or
++ * until client process aborts (read returns 0) */
++ do {
++ ret = read(rpipe[0], &tmp, sizeof(tmp));
++ } while (ret == -1 && errno == EINTR);
++ assert(ret != -1);
++ close(rpipe[0]);
++
++ /* For a clean shutdown */
++ display_run(d);
++
++ display_destroy(d);
++}
++
++static void
++registry_global_remove_before_handle_global(void *data,
++ struct wl_registry *registry,
++ uint32_t id, const char *intf,
++ uint32_t ver)
++{
++ uint32_t *id_ptr = data;
++
++ if (strcmp(intf, wl_seat_interface.name) == 0) {
++ assert(*id_ptr == 0);
++ *id_ptr = id;
++ }
++}
++
++static void
++registry_global_remove_before_handle_global_remove(void *data,
++ struct wl_registry *registry,
++ uint32_t id)
++{
++ uint32_t *id_ptr = data;
++
++ if (*id_ptr == id) {
++ *id_ptr = 0;
++ }
++}
++
++/* This listener expects a uint32_t user data pointer, sets it to the wl_seat
++ * global ID when receiving a "global" event, and sets it to zero when receiving
++ * a "global_remove" event. */
++static const struct wl_registry_listener global_remove_before_registry_listener = {
++ registry_global_remove_before_handle_global,
++ registry_global_remove_before_handle_global_remove,
++};
++
++static void
++global_remove_before_client(void *data)
++{
++ struct client *c = client_connect();
++ struct wl_registry *registry;
++ uint32_t global_id = 0, saved_global_id;
++ struct wl_seat *seat;
++ int ret;
++
++ registry = wl_display_get_registry(c->wl_display);
++ wl_registry_add_listener(registry,
++ &global_remove_before_registry_listener,
++ &global_id);
++
++ ret = wl_display_roundtrip(c->wl_display);
++ assert(ret >= 0);
++ assert(global_id != 0);
++ saved_global_id = global_id;
++
++ /* Wait for the compositor to remove the global */
++ assert(stop_display(c, 1) >= 0);
++
++ /* Check binding still works after the global has been removed. Also
++ * check we get the global_remove event. */
++ seat = wl_registry_bind(registry, saved_global_id, &wl_seat_interface, 1);
++ ret = wl_display_roundtrip(c->wl_display);
++ assert(ret >= 0);
++ assert(global_id == 0);
++
++ wl_seat_destroy(seat);
++ wl_registry_destroy(registry);
++
++ client_disconnect(c);
++}
++
++static void
++registry_global_remove_after_handle_global(void *data,
++ struct wl_registry *registry,
++ uint32_t id, const char *intf,
++ uint32_t ver)
++{
++ /* Make sure the global isn't advertised anymore after being removed */
++ assert(strcmp(intf, wl_seat_interface.name) != 0);
++}
++
++static const struct wl_registry_listener global_remove_after_registry_listener = {
++ registry_global_remove_after_handle_global,
++ NULL,
++};
++
++static void
++global_remove_after_client(void *data)
++{
++ struct client *c = client_connect();
++ struct wl_registry *registry;
++ uint32_t global_id = 0;
++ int ret;
++
++ registry = wl_display_get_registry(c->wl_display);
++ wl_registry_add_listener(registry,
++ &global_remove_after_registry_listener,
++ &global_id);
++
++ ret = wl_display_roundtrip(c->wl_display);
++ assert(ret >= 0);
++
++ wl_registry_destroy(registry);
++
++ client_disconnect(c);
++}
++
++TEST(global_remove)
++{
++ struct display *d;
++ struct wl_global *global;
++
++ d = display_create();
++
++ global = wl_global_create(d->wl_display, &wl_seat_interface,
++ 1, d, bind_seat);
++
++ /* Create a client before removing the global */
++ client_create_noarg(d, global_remove_before_client);
++
++ display_run(d);
++
++ wl_global_remove(global);
++
++ /* Create another client after removing the global */
++ client_create_noarg(d, global_remove_after_client);
++
++ display_resume(d);
++
++ wl_global_destroy(global);
++
++ display_destroy(d);
++}
++
++static void
++terminate_display(void *arg)
++{
++ struct wl_display *wl_display = arg;
++ wl_display_terminate(wl_display);
++}
++
++TEST(no_source_terminate)
++{
++ struct display *d;
++ struct wl_event_loop *loop;
++
++ d = display_create();
++ loop = wl_display_get_event_loop(d->wl_display);
++
++ wl_event_loop_add_idle(loop, terminate_display, d->wl_display);
++
++ display_run(d);
++ display_destroy(d);
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Intel Corporation
++ * Copyright © 2012 Jason Ekstrand
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++#include <stdlib.h>
++#include <stdint.h>
++#include <assert.h>
++#include <unistd.h>
++#include <signal.h>
++#include <string.h>
++#include <sys/time.h>
++
++#include "wayland-private.h"
++#include "wayland-server.h"
++#include "test-runner.h"
++
++static int
++fd_dispatch(int fd, uint32_t mask, void *data)
++{
++ int *p = data;
++
++ assert(mask == 0);
++ ++(*p);
++
++ return 0;
++}
++
++TEST(event_loop_post_dispatch_check)
++{
++ struct wl_event_loop *loop = wl_event_loop_create();
++ struct wl_event_source *source;
++ int dispatch_ran = 0;
++ int p[2];
++
++ assert(loop);
++ assert(pipe(p) == 0);
++
++ source = wl_event_loop_add_fd(loop, p[0], WL_EVENT_READABLE,
++ fd_dispatch, &dispatch_ran);
++ assert(source);
++ wl_event_source_check(source);
++
++ wl_event_loop_dispatch(loop, 0);
++ assert(dispatch_ran == 1);
++
++ assert(close(p[0]) == 0);
++ assert(close(p[1]) == 0);
++ wl_event_source_remove(source);
++ wl_event_loop_destroy(loop);
++}
++
++struct free_source_context {
++ struct wl_event_source *source1, *source2;
++ int p1[2], p2[2];
++ int count;
++};
++
++static int
++free_source_callback(int fd, uint32_t mask, void *data)
++{
++ struct free_source_context *context = data;
++
++ context->count++;
++
++ /* Remove other source */
++ if (fd == context->p1[0]) {
++ wl_event_source_remove(context->source2);
++ context->source2 = NULL;
++ } else if (fd == context->p2[0]) {
++ wl_event_source_remove(context->source1);
++ context->source1 = NULL;
++ } else {
++ assert(0);
++ }
++
++ return 1;
++}
++
++TEST(event_loop_free_source_with_data)
++{
++ struct wl_event_loop *loop = wl_event_loop_create();
++ struct free_source_context context;
++ int data;
++
++ /* This test is a little tricky to get right, since we don't
++ * have any guarantee from the event loop (ie epoll) on the
++ * order of which it reports events. We want to have one
++ * source free the other, but we don't know which one is going
++ * to run first. So we add two fd sources with a callback
++ * that frees the other source and check that only one of them
++ * run (and that we don't crash, of course).
++ */
++
++ assert(loop);
++
++ context.count = 0;
++ assert(pipe(context.p1) == 0);
++ assert(pipe(context.p2) == 0);
++ context.source1 =
++ wl_event_loop_add_fd(loop, context.p1[0], WL_EVENT_READABLE,
++ free_source_callback, &context);
++ assert(context.source1);
++ context.source2 =
++ wl_event_loop_add_fd(loop, context.p2[0], WL_EVENT_READABLE,
++ free_source_callback, &context);
++ assert(context.source2);
++
++ data = 5;
++ assert(write(context.p1[1], &data, sizeof data) == sizeof data);
++ assert(write(context.p2[1], &data, sizeof data) == sizeof data);
++
++ wl_event_loop_dispatch(loop, 0);
++
++ assert(context.count == 1);
++
++ if (context.source1)
++ wl_event_source_remove(context.source1);
++ if (context.source2)
++ wl_event_source_remove(context.source2);
++ wl_event_loop_destroy(loop);
++
++ assert(close(context.p1[0]) == 0);
++ assert(close(context.p1[1]) == 0);
++ assert(close(context.p2[0]) == 0);
++ assert(close(context.p2[1]) == 0);
++}
++
++static int
++signal_callback(int signal_number, void *data)
++{
++ int *got_it = data;
++
++ assert(signal_number == SIGUSR1);
++ ++(*got_it);
++
++ return 1;
++}
++
++TEST(event_loop_signal)
++{
++ struct wl_event_loop *loop = wl_event_loop_create();
++ struct wl_event_source *source;
++ int got_it = 0;
++
++ source = wl_event_loop_add_signal(loop, SIGUSR1,
++ signal_callback, &got_it);
++ assert(source);
++
++ assert(wl_event_loop_dispatch(loop, 0) == 0);
++ assert(!got_it);
++ assert(kill(getpid(), SIGUSR1) == 0);
++ /*
++ * On Linux the signal will be immediately visible in the epoll_wait()
++ * call. However, on FreeBSD we may need a small delay between kill()
++ * call and the signal being visible to the kevent() call. This
++ * sometimes happens when the signal processing and kevent processing
++ * runs on different CPUs, so becomes more likely when the system is
++ * under load (e.g. running all tests in parallel).
++ * See https://github.com/jiixyj/epoll-shim/pull/32
++ * Passing 1ms as the timeout appears to avoid this race condition in
++ * all cases tested so far, but to be safe we use 1000ms which should
++ * be enough time even on a really slow (or emulated) system.
++ */
++ assert(wl_event_loop_dispatch(loop, 1000) == 0);
++ assert(got_it == 1);
++
++ wl_event_source_remove(source);
++ wl_event_loop_destroy(loop);
++}
++
++TEST(event_loop_multiple_same_signals)
++{
++ struct wl_event_loop *loop = wl_event_loop_create();
++ struct wl_event_source *s1, *s2;
++ int calls_no = 0;
++ int i;
++
++ s1 = wl_event_loop_add_signal(loop, SIGUSR1,
++ signal_callback, &calls_no);
++ assert(s1);
++
++ s2 = wl_event_loop_add_signal(loop, SIGUSR1,
++ signal_callback, &calls_no);
++ assert(s2);
++
++ assert(wl_event_loop_dispatch(loop, 0) == 0);
++ assert(!calls_no);
++
++ /* Try it more times */
++ for (i = 0; i < 5; ++i) {
++ calls_no = 0;
++ assert(kill(getpid(), SIGUSR1) == 0);
++ /*
++ * We need a non-zero timeout here to allow the test to pass
++ * on non-Linux systems (see comment in event_loop_signal).
++ */
++ assert(wl_event_loop_dispatch(loop, 1000) == 0);
++ assert(calls_no == 2);
++ }
++
++ wl_event_source_remove(s1);
++
++ /* Try it again with one source */
++ calls_no = 0;
++ assert(kill(getpid(), SIGUSR1) == 0);
++ /*
++ * We need a non-zero timeout here to allow the test to pass
++ * on non-Linux systems (see comment in event_loop_signal).
++ */
++ assert(wl_event_loop_dispatch(loop, 1000) == 0);
++ assert(calls_no == 1);
++
++ wl_event_source_remove(s2);
++
++ wl_event_loop_destroy(loop);
++}
++
++static int
++timer_callback(void *data)
++{
++ int *got_it = data;
++
++ ++(*got_it);
++
++ return 1;
++}
++
++TEST(event_loop_timer)
++{
++ struct wl_event_loop *loop = wl_event_loop_create();
++ struct wl_event_source *source1, *source2;
++ int got_it = 0;
++
++ source1 = wl_event_loop_add_timer(loop, timer_callback, &got_it);
++ assert(source1);
++ wl_event_source_timer_update(source1, 20);
++
++ source2 = wl_event_loop_add_timer(loop, timer_callback, &got_it);
++ assert(source2);
++ wl_event_source_timer_update(source2, 100);
++
++ /* Check that the timer marked for 20 msec from now fires within 30
++ * msec, and that the timer marked for 100 msec is expected to fire
++ * within an additional 90 msec. (Some extra wait time is provided to
++ * account for reasonable code execution / thread preemption delays.) */
++
++ wl_event_loop_dispatch(loop, 0);
++ assert(got_it == 0);
++ wl_event_loop_dispatch(loop, 30);
++ assert(got_it == 1);
++ wl_event_loop_dispatch(loop, 0);
++ assert(got_it == 1);
++ wl_event_loop_dispatch(loop, 90);
++ assert(got_it == 2);
++
++ wl_event_source_remove(source1);
++ wl_event_source_remove(source2);
++ wl_event_loop_destroy(loop);
++}
++
++#define MSEC_TO_USEC(msec) ((msec) * 1000)
++
++struct timer_update_context {
++ struct wl_event_source *source1, *source2;
++ int count;
++};
++
++static int
++timer_update_callback_1(void *data)
++{
++ struct timer_update_context *context = data;
++
++ context->count++;
++ wl_event_source_timer_update(context->source2, 1000);
++ return 1;
++}
++
++static int
++timer_update_callback_2(void *data)
++{
++ struct timer_update_context *context = data;
++
++ context->count++;
++ wl_event_source_timer_update(context->source1, 1000);
++ return 1;
++}
++
++TEST(event_loop_timer_updates)
++{
++ struct wl_event_loop *loop = wl_event_loop_create();
++ struct timer_update_context context;
++ struct timeval start_time, end_time, interval;
++
++ /* Create two timers that should expire at the same time (after 10ms).
++ * The first timer to receive its expiry callback updates the other timer
++ * with a much larger timeout (1s). This highlights a bug where
++ * wl_event_source_timer_dispatch would block for this larger timeout
++ * when reading from the timer fd, before calling the second timer's
++ * callback.
++ */
++
++ context.source1 = wl_event_loop_add_timer(loop, timer_update_callback_1,
++ &context);
++ assert(context.source1);
++ assert(wl_event_source_timer_update(context.source1, 10) == 0);
++
++ context.source2 = wl_event_loop_add_timer(loop, timer_update_callback_2,
++ &context);
++ assert(context.source2);
++ assert(wl_event_source_timer_update(context.source2, 10) == 0);
++
++ context.count = 0;
++
++ /* Since calling the functions between source2's update and
++ * wl_event_loop_dispatch() takes some time, it may happen
++ * that only one timer expires until we call epoll_wait.
++ * This naturally means that only one source is dispatched
++ * and the test fails. To fix that, sleep 15 ms before
++ * calling wl_event_loop_dispatch(). That should be enough
++ * for the second timer to expire.
++ *
++ * https://bugs.freedesktop.org/show_bug.cgi?id=80594
++ */
++ usleep(MSEC_TO_USEC(15));
++
++ gettimeofday(&start_time, NULL);
++ wl_event_loop_dispatch(loop, 20);
++ gettimeofday(&end_time, NULL);
++
++ assert(context.count == 2);
++
++ /* Dispatching the events should not have taken much more than 20ms,
++ * since this is the timeout passed to wl_event_loop_dispatch. If it
++ * blocked, then it will have taken over 1s.
++ * Of course, it could take over 1s anyway on a very slow or heavily
++ * loaded system, so this test isn't 100% perfect.
++ */
++
++ timersub(&end_time, &start_time, &interval);
++ assert(interval.tv_sec < 1);
++
++ wl_event_source_remove(context.source1);
++ wl_event_source_remove(context.source2);
++ wl_event_loop_destroy(loop);
++}
++
++struct timer_order_data {
++ struct wl_event_source *source;
++ int *last_number;
++ int number;
++};
++
++static int
++timer_order_callback(void *data)
++{
++ struct timer_order_data *tod = data;
++
++ /* Check that the timers have the correct sequence */
++ assert(tod->number == *tod->last_number + 2);
++ *tod->last_number = tod->number;
++ return 0;
++}
++
++TEST(event_loop_timer_order)
++{
++ struct wl_event_loop *loop = wl_event_loop_create();
++ struct timer_order_data order[20];
++ int i, j;
++ int last = -1;
++
++ /* Configure a set of timers so that only timers 1, 3, 5, ..., 19
++ * (in that order) will be dispatched when the event loop is run */
++
++ for (i = 0; i < 20; i++) {
++ order[i].number = i;
++ order[i].last_number = &last;
++ order[i].source =
++ wl_event_loop_add_timer(loop, timer_order_callback,
++ &order[i]);
++ assert(order[i].source);
++ assert(wl_event_source_timer_update(order[i].source, 10) == 0);
++ }
++
++ for (i = 0; i < 20; i++) {
++ /* Permute the order in which timers are updated, so as to
++ * more exhaustively test the underlying priority queue code */
++ j = ((i + 3) * 17) % 20;
++ assert(wl_event_source_timer_update(order[j].source, j) == 0);
++ }
++ for (i = 0; i < 20; i += 2) {
++ assert(wl_event_source_timer_update(order[i].source, 0) == 0);
++ }
++
++ /* Wait until all timers are due */
++ usleep(MSEC_TO_USEC(21));
++ wl_event_loop_dispatch(loop, 0);
++ assert(last == 19);
++
++ for (i = 0; i < 20; i++) {
++ wl_event_source_remove(order[i].source);
++ }
++ wl_event_loop_destroy(loop);
++}
++
++struct timer_cancel_context {
++ struct wl_event_source *timers[4];
++ struct timer_cancel_context *back_refs[4];
++ int order[4];
++ int called, first;
++};
++
++static int
++timer_cancel_callback(void *data) {
++ struct timer_cancel_context **context_ref = data;
++ struct timer_cancel_context *context = *context_ref;
++ int i = (int)(context_ref - context->back_refs);
++
++ context->called++;
++ context->order[i] = context->called;
++
++ if (context->called == 1) {
++ context->first = i;
++ /* Removing a timer always prevents its callback from
++ * being called ... */
++ wl_event_source_remove(context->timers[(i + 1) % 4]);
++ /* ... but disarming or rescheduling a timer does not,
++ * (in the case where the modified timers had already expired
++ * as of when `wl_event_loop_dispatch` was called.) */
++ assert(wl_event_source_timer_update(context->timers[(i + 2) % 4],
++ 0) == 0);
++ assert(wl_event_source_timer_update(context->timers[(i + 3) % 4],
++ 2000000000) == 0);
++ }
++
++ return 0;
++}
++
++TEST(event_loop_timer_cancellation)
++{
++ struct wl_event_loop *loop = wl_event_loop_create();
++ struct timer_cancel_context context;
++ int i;
++
++ memset(&context, 0, sizeof(context));
++
++ /* Test that when multiple timers are dispatched in a single call
++ * of `wl_event_loop_dispatch`, that having some timers run code
++ * to modify the other timers only actually prevents the other timers
++ * from running their callbacks when the those timers are removed, not
++ * when they are disarmed or rescheduled. */
++
++ for (i = 0; i < 4; i++) {
++ context.back_refs[i] = &context;
++ context.timers[i] =
++ wl_event_loop_add_timer(loop, timer_cancel_callback,
++ &context.back_refs[i]);
++ assert(context.timers[i]);
++
++ assert(wl_event_source_timer_update(context.timers[i], 1) == 0);
++ }
++
++ usleep(MSEC_TO_USEC(2));
++ assert(wl_event_loop_dispatch(loop, 0) == 0);
++
++ /* Tracking which timer was first makes this test independent of the
++ * actual timer dispatch order, which is not guaranteed by the docs */
++ assert(context.order[context.first] == 1);
++ assert(context.order[(context.first + 1) % 4] == 0);
++ assert(context.order[(context.first + 2) % 4] > 1);
++ assert(context.order[(context.first + 3) % 4] > 1);
++
++ wl_event_source_remove(context.timers[context.first]);
++ wl_event_source_remove(context.timers[(context.first + 2) % 4]);
++ wl_event_source_remove(context.timers[(context.first + 3) % 4]);
++
++ wl_event_loop_destroy(loop);
++}
++
++struct event_loop_destroy_listener {
++ struct wl_listener listener;
++ int done;
++};
++
++static void
++event_loop_destroy_notify(struct wl_listener *l, void *data)
++{
++ struct event_loop_destroy_listener *listener =
++ wl_container_of(l, listener, listener);
++
++ listener->done = 1;
++}
++
++TEST(event_loop_destroy)
++{
++ struct wl_event_loop *loop;
++ struct wl_display * display;
++ struct event_loop_destroy_listener a, b;
++
++ loop = wl_event_loop_create();
++ assert(loop);
++
++ a.listener.notify = &event_loop_destroy_notify;
++ a.done = 0;
++ wl_event_loop_add_destroy_listener(loop, &a.listener);
++
++ assert(wl_event_loop_get_destroy_listener(loop,
++ event_loop_destroy_notify) == &a.listener);
++
++ b.listener.notify = &event_loop_destroy_notify;
++ b.done = 0;
++ wl_event_loop_add_destroy_listener(loop, &b.listener);
++
++ wl_list_remove(&a.listener.link);
++ wl_event_loop_destroy(loop);
++
++ assert(!a.done);
++ assert(b.done);
++
++ /* Test to make sure it gets fired on display destruction */
++ display = wl_display_create();
++ assert(display);
++ loop = wl_display_get_event_loop(display);
++ assert(loop);
++
++ a.done = 0;
++ wl_event_loop_add_destroy_listener(loop, &a.listener);
++
++ wl_display_destroy(display);
++
++ assert(a.done);
++}
++
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <errno.h>
++#include <limits.h>
++
++#include "test-runner.h"
++
++static int
++parse_count(const char *str, int *value)
++{
++ char *end;
++ long v;
++
++ errno = 0;
++ v = strtol(str, &end, 10);
++ if ((errno == ERANGE && (v == LONG_MAX || v == LONG_MIN)) ||
++ (errno != 0 && v == 0) ||
++ (end == str) ||
++ (*end != '\0')) {
++ return -1;
++ }
++
++ if (v < 0 || v > INT_MAX) {
++ return -1;
++ }
++
++ *value = v;
++ return 0;
++}
++
++int main(int argc, char *argv[])
++{
++ int expected;
++
++ if (argc != 2)
++ goto help_out;
++
++ if (parse_count(argv[1], &expected) < 0)
++ goto help_out;
++
++ if (count_open_fds() == expected)
++ return EXIT_SUCCESS;
++ else
++ return EXIT_FAILURE;
++
++help_out:
++ fprintf(stderr, "Usage: %s N\n"
++ "where N is the expected number of open file descriptors.\n"
++ "This program exits with a failure if the number "
++ "does not match exactly.\n", argv[0]);
++
++ return EXIT_FAILURE;
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <time.h>
++#include <assert.h>
++#include "wayland-private.h"
++
++volatile double global_d;
++
++static void
++noop_conversion(void)
++{
++ wl_fixed_t f;
++ union {
++ int64_t i;
++ double d;
++ } u;
++
++ for (f = 0; f < INT32_MAX; f++) {
++ u.i = f;
++ global_d = u.d;
++ }
++}
++
++static void
++magic_conversion(void)
++{
++ wl_fixed_t f;
++
++ for (f = 0; f < INT32_MAX; f++)
++ global_d = wl_fixed_to_double(f);
++}
++
++static void
++mul_conversion(void)
++{
++ wl_fixed_t f;
++
++ /* This will get optimized into multiplication by 1/256 */
++ for (f = 0; f < INT32_MAX; f++)
++ global_d = f / 256.0;
++}
++
++double factor = 256.0;
++
++static void
++div_conversion(void)
++{
++ wl_fixed_t f;
++
++ for (f = 0; f < INT32_MAX; f++)
++ global_d = f / factor;
++}
++
++static void
++benchmark(const char *s, void (*f)(void))
++{
++ struct timespec start, stop, elapsed;
++
++ clock_gettime(CLOCK_MONOTONIC, &start);
++ f();
++ clock_gettime(CLOCK_MONOTONIC, &stop);
++
++ elapsed.tv_sec = stop.tv_sec - start.tv_sec;
++ elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec;
++ if (elapsed.tv_nsec < 0) {
++ elapsed.tv_nsec += 1000000000;
++ elapsed.tv_sec--;
++ }
++ printf("benchmarked %s:\t%ld.%09lds\n",
++ s, elapsed.tv_sec, elapsed.tv_nsec);
++}
++
++int main(void)
++{
++ benchmark("noop", noop_conversion);
++ benchmark("magic", magic_conversion);
++ benchmark("div", div_conversion);
++ benchmark("mul", mul_conversion);
++
++ return 0;
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++#include <stdlib.h>
++#include <stdio.h>
++#include <assert.h>
++#include "wayland-private.h"
++#include "test-runner.h"
++
++TEST(fixed_double_conversions)
++{
++ wl_fixed_t f;
++ double d;
++
++ d = 62.125;
++ f = wl_fixed_from_double(d);
++ fprintf(stderr, "double %lf to fixed %x\n", d, f);
++ assert(f == 0x3e20);
++
++ d = -1200.625;
++ f = wl_fixed_from_double(d);
++ fprintf(stderr, "double %lf to fixed %x\n", d, f);
++ assert(f == -0x4b0a0);
++
++ f = random();
++ d = wl_fixed_to_double(f);
++ fprintf(stderr, "fixed %x to double %lf\n", f, d);
++ assert(d == f / 256.0);
++
++ f = 0x012030;
++ d = wl_fixed_to_double(f);
++ fprintf(stderr, "fixed %x to double %lf\n", f, d);
++ assert(d == 288.1875);
++
++ f = 0x70000000;
++ d = wl_fixed_to_double(f);
++ fprintf(stderr, "fixed %x to double %lf\n", f, d);
++ assert(d == f / 256);
++
++ f = -0x012030;
++ d = wl_fixed_to_double(f);
++ fprintf(stderr, "fixed %x to double %lf\n", f, d);
++ assert(d == -288.1875);
++
++ f = 0x80000000;
++ d = wl_fixed_to_double(f);
++ fprintf(stderr, "fixed %x to double %lf\n", f, d);
++ assert(d == f / 256);
++}
++
++TEST(fixed_int_conversions)
++{
++ wl_fixed_t f;
++ int i;
++
++ i = 62;
++ f = wl_fixed_from_int(i);
++ assert(f == 62 * 256);
++
++ i = -2080;
++ f = wl_fixed_from_int(i);
++ assert(f == -2080 * 256);
++
++ f = 0x277013;
++ i = wl_fixed_to_int(f);
++ assert(i == 0x2770);
++
++ f = -0x5044;
++ i = wl_fixed_to_int(f);
++ assert(i == -0x50);
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2015 Giulio Camuffo
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "wayland-client-protocol-core.h"
++#include "wayland-server-protocol-core.h"
++
++#ifndef WAYLAND_CLIENT_CORE_H
++#error including wayland-client-protocol-core.h did not include wayland-client-core.h!
++#endif
++#ifndef WAYLAND_SERVER_CORE_H
++#error including wayland-server-protocol-core.h did not include wayland-server-core.h!
++#endif
++
++#ifdef WAYLAND_CLIENT_H
++#error including wayland-client-protocol-core.h included wayland-client.h!
++#endif
++#ifdef WAYLAND_SERVER_H
++#error including wayland-server-protocol-core.h included wayland-server.h!
++#endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2015 Giulio Camuffo
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "wayland-client-protocol.h"
++#include "wayland-server-protocol.h"
++
++#ifndef WAYLAND_CLIENT_H
++#error including wayland-client-protocol.h did not include wayland-client.h!
++#endif
++#ifndef WAYLAND_SERVER_H
++#error including wayland-server-protocol.h did not include wayland-server.h!
++#endif
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2015 Giulio Camuffo
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "wayland-client-core.h"
++#include "wayland-server-core.h"
++
++#ifdef WL_DISPLAY_SYNC
++#error including wayland-client-core.h imported protocol symbols!
++#endif
++#ifdef WL_DISPLAY_ERROR
++#error including wayland-server-core.h imported protocol symbols!
++#endif
++
++#ifdef WAYLAND_CLIENT_H
++#error including wayland-client-core.h included the non-core header!
++#endif
++#ifdef WAYLAND_SERVER_H
++#error including wayland-server-core.h included the non-core header!
++#endif
++
++#include "wayland-client.h"
++#include "wayland-server.h"
++
++#ifndef WL_DISPLAY_SYNC
++#error including wayland-client.h did not import protocol symbols!
++#endif
++#ifndef WL_DISPLAY_ERROR
++#error including wayland-server.h did not import protocol symbols!
++#endif
++
++int main(int argc, char **argv) { return 0; }
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2016 Yong Bakos
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++
++#include "wayland-client.h"
++#include "wayland-private.h"
++#include "test-runner.h"
++
++TEST(interface_equal)
++{
++ const struct wl_interface fake = {
++ "fake", 1, 0, NULL, 0, NULL
++ };
++ const struct wl_interface fake_registry = {
++ "wl_registry", 1, 0, NULL, 0, NULL
++ };
++ const struct wl_interface copy = wl_registry_interface;
++
++ assert(&wl_registry_interface != ©);
++
++ assert(wl_interface_equal(&wl_registry_interface,
++ &wl_registry_interface));
++ assert(wl_interface_equal(&wl_registry_interface, ©));
++ assert(wl_interface_equal(&wl_registry_interface,
++ &fake_registry));
++ assert(!wl_interface_equal(&wl_registry_interface, &fake));
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <assert.h>
++#include "wayland-private.h"
++#include "test-runner.h"
++
++TEST(list_init)
++{
++ struct wl_list list;
++
++ wl_list_init(&list);
++ assert(list.next == &list);
++ assert(list.prev == &list);
++ assert(wl_list_empty(&list));
++}
++
++struct element {
++ int i;
++ struct wl_list link;
++};
++
++TEST(list_insert)
++{
++ struct wl_list list;
++ struct element e;
++
++ wl_list_init(&list);
++ wl_list_insert(&list, &e.link);
++ assert(list.next == &e.link);
++ assert(list.prev == &e.link);
++ assert(e.link.next == &list);
++ assert(e.link.prev == &list);
++}
++
++TEST(list_length)
++{
++ struct wl_list list;
++ struct element e;
++
++ wl_list_init(&list);
++ assert(wl_list_length(&list) == 0);
++ wl_list_insert(&list, &e.link);
++ assert(wl_list_length(&list) == 1);
++ wl_list_remove(&e.link);
++ assert(wl_list_length(&list) == 0);
++}
++
++TEST(list_iterator)
++{
++ struct wl_list list;
++ struct element e1, e2, e3, e4, *e;
++ int reference[] = { 708090, 102030, 5588, 12 };
++ unsigned int i;
++
++ e1.i = 708090;
++ e2.i = 102030;
++ e3.i = 5588;
++ e4.i = 12;
++
++ wl_list_init(&list);
++ wl_list_insert(list.prev, &e1.link);
++ wl_list_insert(list.prev, &e2.link);
++ wl_list_insert(list.prev, &e3.link);
++ wl_list_insert(list.prev, &e4.link);
++
++ i = 0;
++ wl_list_for_each(e, &list, link) {
++ assert(i < ARRAY_LENGTH(reference));
++ assert(e->i == reference[i]);
++ i++;
++ }
++ assert(i == ARRAY_LENGTH(reference));
++
++ i = 0;
++ wl_list_for_each_reverse(e, &list, link) {
++ assert(i < ARRAY_LENGTH(reference));
++ assert(e->i == reference[ARRAY_LENGTH(reference) - i - 1]);
++ i++;
++ }
++ assert(i == ARRAY_LENGTH(reference));
++}
++
++static int
++validate_list(struct wl_list *list, int *reference, int length)
++{
++ struct element *e;
++ int i;
++
++ i = 0;
++ wl_list_for_each(e, list, link) {
++ if (i >= length)
++ return 0;
++ if (e->i != reference[i])
++ return 0;
++ i++;
++ }
++
++ if (i != length)
++ return 0;
++
++ return 1;
++}
++
++TEST(list_remove)
++{
++ struct wl_list list;
++ struct element e1, e2, e3;
++ int reference1[] = { 17, 8888, 1000 }, reference2[] = { 17, 1000 };
++
++ e1.i = 17;
++ e2.i = 8888;
++ e3.i = 1000;
++
++ wl_list_init(&list);
++ wl_list_insert(&list, &e1.link);
++ wl_list_insert(list.prev, &e2.link);
++ wl_list_insert(list.prev, &e3.link);
++ assert(validate_list(&list, reference1, ARRAY_LENGTH(reference1)));
++
++ wl_list_remove(&e2.link);
++ assert(validate_list(&list, reference2, ARRAY_LENGTH(reference2)));
++}
++
++TEST(list_insert_list)
++{
++ struct wl_list list, other;
++ struct element e1, e2, e3, e4, e5, e6;
++ int reference1[] = { 17, 8888, 1000 };
++ int reference2[] = { 76543, 1, -500 };
++ int reference3[] = { 17, 76543, 1, -500, 8888, 1000 };
++
++ e1.i = 17;
++ e2.i = 8888;
++ e3.i = 1000;
++
++ wl_list_init(&list);
++ wl_list_insert(&list, &e1.link);
++ wl_list_insert(list.prev, &e2.link);
++ wl_list_insert(list.prev, &e3.link);
++ assert(validate_list(&list, reference1, ARRAY_LENGTH(reference1)));
++
++ e4.i = 76543;
++ e5.i = 1;
++ e6.i = -500;
++
++ wl_list_init(&other);
++ wl_list_insert(&other, &e4.link);
++ wl_list_insert(other.prev, &e5.link);
++ wl_list_insert(other.prev, &e6.link);
++ assert(validate_list(&other, reference2, ARRAY_LENGTH(reference2)));
++
++ wl_list_insert_list(list.next, &other);
++ assert(validate_list(&list, reference3, ARRAY_LENGTH(reference3)));
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <assert.h>
++#include "wayland-private.h"
++#include "test-runner.h"
++
++TEST(map_insert_new)
++{
++ struct wl_map map;
++ uint32_t i, j, k, a, b, c;
++
++ wl_map_init(&map, WL_MAP_SERVER_SIDE);
++ i = wl_map_insert_new(&map, 0, &a);
++ j = wl_map_insert_new(&map, 0, &b);
++ k = wl_map_insert_new(&map, 0, &c);
++ assert(i == WL_SERVER_ID_START);
++ assert(j == WL_SERVER_ID_START + 1);
++ assert(k == WL_SERVER_ID_START + 2);
++
++ assert(wl_map_lookup(&map, i) == &a);
++ assert(wl_map_lookup(&map, j) == &b);
++ assert(wl_map_lookup(&map, k) == &c);
++ wl_map_release(&map);
++
++ wl_map_init(&map, WL_MAP_CLIENT_SIDE);
++ i = wl_map_insert_new(&map, 0, &a);
++ assert(i == 0);
++ assert(wl_map_lookup(&map, i) == &a);
++
++ wl_map_release(&map);
++}
++
++TEST(map_insert_at)
++{
++ struct wl_map map;
++ uint32_t a, b, c;
++
++ wl_map_init(&map, WL_MAP_CLIENT_SIDE);
++ assert(wl_map_insert_at(&map, 0, WL_SERVER_ID_START, &a) == 0);
++ assert(wl_map_insert_at(&map, 0, WL_SERVER_ID_START + 3, &b) == -1);
++ assert(wl_map_insert_at(&map, 0, WL_SERVER_ID_START + 1, &c) == 0);
++
++ assert(wl_map_lookup(&map, WL_SERVER_ID_START) == &a);
++ assert(wl_map_lookup(&map, WL_SERVER_ID_START + 1) == &c);
++
++ wl_map_release(&map);
++}
++
++TEST(map_remove)
++{
++ struct wl_map map;
++ uint32_t i, j, k, l, a, b, c, d;
++
++ wl_map_init(&map, WL_MAP_SERVER_SIDE);
++ i = wl_map_insert_new(&map, 0, &a);
++ j = wl_map_insert_new(&map, 0, &b);
++ k = wl_map_insert_new(&map, 0, &c);
++ assert(i == WL_SERVER_ID_START);
++ assert(j == WL_SERVER_ID_START + 1);
++ assert(k == WL_SERVER_ID_START + 2);
++
++ assert(wl_map_lookup(&map, i) == &a);
++ assert(wl_map_lookup(&map, j) == &b);
++ assert(wl_map_lookup(&map, k) == &c);
++
++ wl_map_remove(&map, j);
++ assert(wl_map_lookup(&map, j) == NULL);
++
++ /* Verify that we insert d at the hole left by removing b */
++ l = wl_map_insert_new(&map, 0, &d);
++ assert(l == WL_SERVER_ID_START + 1);
++ assert(wl_map_lookup(&map, l) == &d);
++
++ wl_map_release(&map);
++}
++
++TEST(map_flags)
++{
++ struct wl_map map;
++ uint32_t i, j, a, b;
++
++ wl_map_init(&map, WL_MAP_SERVER_SIDE);
++ i = wl_map_insert_new(&map, 0, &a);
++ j = wl_map_insert_new(&map, 1, &b);
++ assert(i == WL_SERVER_ID_START);
++ assert(j == WL_SERVER_ID_START + 1);
++
++ assert(wl_map_lookup(&map, i) == &a);
++ assert(wl_map_lookup(&map, j) == &b);
++
++ assert(wl_map_lookup_flags(&map, i) == 0);
++ assert(wl_map_lookup_flags(&map, j) == 1);
++
++ wl_map_release(&map);
++}
++
++static enum wl_iterator_result never_run(void *element, void *data, uint32_t flags)
++{
++ assert(0);
++}
++
++TEST(map_iter_empty)
++{
++ struct wl_map map;
++
++ wl_map_init(&map, WL_MAP_SERVER_SIDE);
++
++ wl_map_for_each(&map, never_run, NULL);
++
++ wl_map_release(&map);
++}
--- /dev/null
--- /dev/null
++if not get_option('libraries')
++ error('-Dtests=true requires -Dlibraries=true')
++endif
++
++test_runner = static_library(
++ 'test-runner',
++ sources: [
++ 'test-runner.c',
++ 'test-helpers.c',
++ 'test-compositor.c'
++ ],
++ include_directories: [ root_inc, src_inc ],
++ dependencies: [
++ cc.find_library('dl', required: false),
++ dependency('threads'),
++ epoll_dep,
++ ffi_dep,
++ wayland_util_dep,
++ wayland_private_dep,
++ wayland_client_dep,
++ wayland_server_dep
++ ]
++)
++
++test_runner_dep = declare_dependency(
++ link_with: test_runner,
++ include_directories: [ src_inc ],
++ dependencies: [
++ dependency('threads'),
++ cc.find_library('dl', required: false)
++ ]
++)
++
++tests_protocol_xml = files('../protocol/tests.xml')
++
++tests_server_protocol_h = custom_target(
++ 'test server protocol header',
++ command: [ wayland_scanner_for_build, '-s', 'server-header', '@INPUT@', '@OUTPUT@' ],
++ input: tests_protocol_xml,
++ output: 'tests-server-protocol.h'
++)
++
++tests_client_protocol_c = custom_target(
++ 'test client protocol header',
++ command: [ wayland_scanner_for_build, '-s', 'client-header', '@INPUT@', '@OUTPUT@' ],
++ input: tests_protocol_xml,
++ output: 'tests-client-protocol.h'
++)
++
++tests_protocol_c = custom_target(
++ 'test protocol source',
++ command: [ wayland_scanner_for_build, '-s', 'public-code', '@INPUT@', '@OUTPUT@' ],
++ input: tests_protocol_xml,
++ output: 'tests-protocol.c'
++)
++
++benchmark(
++ 'fixed-benchmark',
++ executable(
++ 'fixed-benchmark',
++ 'fixed-benchmark.c',
++ dependencies: [ test_runner_dep, rt_dep ]
++ )
++)
++
++executable(
++ 'exec-fd-leak-checker',
++ 'exec-fd-leak-checker.c',
++ dependencies: test_runner_dep
++)
++
++if add_languages('cpp', native: false)
++ test(
++ 'cpp-compile-test',
++ executable(
++ 'cpp-compile-test',
++ 'cpp-compile-test.cpp',
++ wayland_server_protocol_h,
++ include_directories: src_inc
++ )
++ )
++endif
++
++sed_path = find_program('sed').full_path()
++
++if get_option('scanner')
++ test(
++ 'scanner-test',
++ find_program('scanner-test.sh'),
++ env: [
++ 'TEST_DATA_DIR=@0@/data'.format(meson.current_source_dir()),
++ 'TEST_OUTPUT_DIR=@0@/output'.format(meson.current_build_dir()),
++ 'SED=@0@'.format(sed_path),
++ 'WAYLAND_SCANNER=@0@'.format(wayland_scanner.full_path()),
++ ],
++ )
++endif
++
++tests = {
++ 'array-test': [],
++ 'client-test': [ wayland_server_protocol_h ],
++ 'display-test': [
++ wayland_client_protocol_h,
++ wayland_server_protocol_h,
++ tests_server_protocol_h,
++ tests_client_protocol_c,
++ tests_protocol_c,
++ ],
++ 'connection-test': [
++ wayland_client_protocol_h,
++ wayland_server_protocol_h,
++ ],
++ 'event-loop-test': [ wayland_server_protocol_h ],
++ 'fixed-test': [],
++ 'interface-test': [ wayland_client_protocol_h ],
++ 'list-test': [],
++ 'map-test': [],
++ 'sanity-test' : [
++ wayland_client_protocol_h,
++ wayland_server_protocol_h,
++ ],
++ 'socket-test': [
++ wayland_client_protocol_h,
++ wayland_server_protocol_h,
++ ],
++ 'queue-test': [
++ wayland_client_protocol_h,
++ wayland_server_protocol_h,
++ ],
++ 'signal-test': [ wayland_server_protocol_h ],
++ 'newsignal-test': [
++ # wayland-server.c is needed here to access wl_priv_* functions
++ files('../src/wayland-server.c'),
++ wayland_server_protocol_h,
++ ],
++ 'resources-test': [ wayland_server_protocol_h ],
++ 'message-test': [
++ wayland_client_protocol_h,
++ wayland_server_protocol_h,
++ ],
++ 'compositor-introspection-test': [
++ wayland_client_protocol_h,
++ wayland_server_protocol_h,
++ ],
++ 'protocol-logger-test': [
++ wayland_client_protocol_h,
++ wayland_server_protocol_h,
++ ],
++ 'headers-test': [
++ wayland_client_protocol_h,
++ wayland_server_protocol_h,
++ 'headers-protocol-test.c',
++ wayland_client_protocol_core_h,
++ wayland_server_protocol_core_h,
++ 'headers-protocol-core-test.c',
++ ],
++ 'os-wrappers-test': [],
++}
++
++foreach test_name, test_extra_sources: tests
++ test_sources = [ test_name + '.c' ] + test_extra_sources
++ test_deps = [test_runner_dep, epoll_dep]
++ bin = executable(test_name, test_sources, dependencies: test_deps)
++ test(
++ test_name,
++ bin,
++ env: [
++ 'TEST_SRC_DIR=@0@'.format(meson.current_source_dir()),
++ 'TEST_BUILD_DIR=@0@'.format(meson.current_build_dir()),
++ ],
++ )
++endforeach
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2014 Jonas Ådahl
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++
++#include "wayland-client.h"
++#include "wayland-private.h"
++#include "wayland-server.h"
++#include "test-runner.h"
++
++TEST(message_version)
++{
++ unsigned int i;
++ const struct {
++ const struct wl_message *message;
++ int expected_version;
++ } messages[] = {
++ { &wl_pointer_interface.events[WL_POINTER_ENTER], 1 },
++ { &wl_surface_interface.events[WL_SURFACE_ENTER], 1 },
++ { &wl_pointer_interface.methods[WL_POINTER_SET_CURSOR], 1 },
++ { &wl_pointer_interface.methods[WL_POINTER_RELEASE], 3 },
++ { &wl_surface_interface.methods[WL_SURFACE_DESTROY], 1 },
++ { &wl_surface_interface.methods[WL_SURFACE_SET_BUFFER_TRANSFORM], 2 },
++ { &wl_surface_interface.methods[WL_SURFACE_SET_BUFFER_SCALE], 3 },
++ };
++
++ for (i = 0; i < ARRAY_LENGTH(messages); ++i) {
++ assert(wl_message_get_since(messages[i].message) ==
++ messages[i].expected_version);
++ }
++}
++
++TEST(message_count_arrays)
++{
++ unsigned int i;
++ struct wl_message fake_messages[] = {
++ { "empty", "", NULL },
++ { "non_present", "iufsonh", NULL },
++ { "leading", "aiufsonh", NULL},
++ { "trailing", "iufsonha", NULL },
++ { "middle", "iufasonh", NULL },
++ { "multiple", "aaiufaasonhaa", NULL },
++ { "leading_version", "2aaiufaasonhaa", NULL },
++ { "among_nullables", "iufsa?oa?sah", NULL },
++ { "all_mixed", "2aiufas?oa?sa", NULL },
++ };
++ const struct {
++ const struct wl_message *message;
++ int expected_array_count;
++ } messages[] = {
++ { &wl_pointer_interface.events[WL_POINTER_ENTER], 0 },
++ { &wl_keyboard_interface.events[WL_KEYBOARD_ENTER], 1 },
++ { &fake_messages[0], 0 },
++ { &fake_messages[1], 0 },
++ { &fake_messages[2], 1 },
++ { &fake_messages[3], 1 },
++ { &fake_messages[4], 1 },
++ { &fake_messages[5], 6 },
++ { &fake_messages[6], 6 },
++ { &fake_messages[7], 3 },
++ { &fake_messages[8], 4 },
++ };
++
++ for (i = 0; i < ARRAY_LENGTH(messages); ++i) {
++ assert(wl_message_count_arrays(messages[i].message) ==
++ messages[i].expected_array_count);
++ }
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2013 Marek Chalupa
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++
++#include "test-runner.h"
++#include "wayland-server-private.h"
++
++static void
++signal_notify(struct wl_listener *listener, void *data)
++{
++ /* only increase counter*/
++ ++(*((int *) data));
++}
++
++TEST(signal_init)
++{
++ struct wl_priv_signal signal;
++
++ wl_priv_signal_init(&signal);
++
++ /* Test if listeners' list is initialized */
++ assert(&signal.listener_list == signal.listener_list.next
++ && "Maybe wl_priv_signal implementation changed?");
++ assert(signal.listener_list.next == signal.listener_list.prev
++ && "Maybe wl_priv_signal implementation changed?");
++}
++
++TEST(signal_add_get)
++{
++ struct wl_priv_signal signal;
++
++ /* we just need different values of notify */
++ struct wl_listener l1 = {.notify = (wl_notify_func_t) 0x1};
++ struct wl_listener l2 = {.notify = (wl_notify_func_t) 0x2};
++ struct wl_listener l3 = {.notify = (wl_notify_func_t) 0x3};
++ /* one real, why not */
++ struct wl_listener l4 = {.notify = signal_notify};
++
++ wl_priv_signal_init(&signal);
++
++ wl_priv_signal_add(&signal, &l1);
++ wl_priv_signal_add(&signal, &l2);
++ wl_priv_signal_add(&signal, &l3);
++ wl_priv_signal_add(&signal, &l4);
++
++ assert(wl_priv_signal_get(&signal, signal_notify) == &l4);
++ assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x3) == &l3);
++ assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x2) == &l2);
++ assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x1) == &l1);
++
++ /* get should not be destructive */
++ assert(wl_priv_signal_get(&signal, signal_notify) == &l4);
++ assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x3) == &l3);
++ assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x2) == &l2);
++ assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x1) == &l1);
++}
++
++TEST(signal_emit_to_one_listener)
++{
++ int count = 0;
++ int counter;
++
++ struct wl_priv_signal signal;
++ struct wl_listener l1 = {.notify = signal_notify};
++
++ wl_priv_signal_init(&signal);
++ wl_priv_signal_add(&signal, &l1);
++
++ for (counter = 0; counter < 100; counter++)
++ wl_priv_signal_emit(&signal, &count);
++
++ assert(counter == count);
++}
++
++TEST(signal_emit_to_more_listeners)
++{
++ int count = 0;
++ int counter;
++
++ struct wl_priv_signal signal;
++ struct wl_listener l1 = {.notify = signal_notify};
++ struct wl_listener l2 = {.notify = signal_notify};
++ struct wl_listener l3 = {.notify = signal_notify};
++
++ wl_priv_signal_init(&signal);
++ wl_priv_signal_add(&signal, &l1);
++ wl_priv_signal_add(&signal, &l2);
++ wl_priv_signal_add(&signal, &l3);
++
++ for (counter = 0; counter < 100; counter++)
++ wl_priv_signal_emit(&signal, &count);
++
++ assert(3 * counter == count);
++}
++
++struct signal
++{
++ struct wl_priv_signal signal;
++ struct wl_listener l1, l2, l3;
++ int count;
++ struct wl_listener *current;
++};
++
++static void notify_remove(struct wl_listener *l, void *data)
++{
++ struct signal *sig = data;
++ wl_list_remove(&sig->current->link);
++ wl_list_init(&sig->current->link);
++ sig->count++;
++}
++
++#define INIT \
++ wl_priv_signal_init(&signal.signal); \
++ wl_list_init(&signal.l1.link); \
++ wl_list_init(&signal.l2.link); \
++ wl_list_init(&signal.l3.link);
++#define CHECK_EMIT(expected) \
++ signal.count = 0; \
++ wl_priv_signal_emit(&signal.signal, &signal); \
++ assert(signal.count == expected);
++
++TEST(signal_remove_listener)
++{
++ test_set_timeout(4);
++
++ struct signal signal;
++
++ signal.l1.notify = notify_remove;
++ signal.l2.notify = notify_remove;
++ signal.l3.notify = notify_remove;
++
++ INIT
++ wl_priv_signal_add(&signal.signal, &signal.l1);
++
++ signal.current = &signal.l1;
++ CHECK_EMIT(1)
++ CHECK_EMIT(0)
++
++ INIT
++ wl_priv_signal_add(&signal.signal, &signal.l1);
++ wl_priv_signal_add(&signal.signal, &signal.l2);
++
++ CHECK_EMIT(2)
++ CHECK_EMIT(1)
++
++ INIT
++ wl_priv_signal_add(&signal.signal, &signal.l1);
++ wl_priv_signal_add(&signal.signal, &signal.l2);
++
++ signal.current = &signal.l2;
++ CHECK_EMIT(1)
++ CHECK_EMIT(1)
++
++ INIT
++ wl_priv_signal_add(&signal.signal, &signal.l1);
++ wl_priv_signal_add(&signal.signal, &signal.l2);
++ wl_priv_signal_add(&signal.signal, &signal.l3);
++
++ signal.current = &signal.l1;
++ CHECK_EMIT(3)
++ CHECK_EMIT(2)
++
++ INIT
++ wl_priv_signal_add(&signal.signal, &signal.l1);
++ wl_priv_signal_add(&signal.signal, &signal.l2);
++ wl_priv_signal_add(&signal.signal, &signal.l3);
++
++ signal.current = &signal.l2;
++ CHECK_EMIT(2)
++ CHECK_EMIT(2)
++
++ INIT
++ wl_priv_signal_add(&signal.signal, &signal.l1);
++ wl_priv_signal_add(&signal.signal, &signal.l2);
++ wl_priv_signal_add(&signal.signal, &signal.l3);
++
++ signal.current = &signal.l3;
++ CHECK_EMIT(2)
++ CHECK_EMIT(2)
++}
++
++static void notify_readd(struct wl_listener *l, void *data)
++{
++ struct signal *signal = data;
++ if (signal->current) {
++ wl_list_remove(&signal->current->link);
++ wl_list_init(&signal->current->link);
++ wl_priv_signal_add(&signal->signal, signal->current);
++ }
++ signal->count++;
++}
++
++static void notify_empty(struct wl_listener *l, void *data)
++{
++ struct signal *signal = data;
++ signal->count++;
++}
++
++TEST(signal_readd_listener)
++{
++ /* Readding a listener is supported, that is it doesn't trigger an
++ * infinite loop or other weird things, but if in a listener you
++ * re-add another listener, that will not be fired in the current
++ * signal emission. */
++
++ test_set_timeout(4);
++
++ struct signal signal;
++
++ signal.l1.notify = notify_readd;
++ signal.l2.notify = notify_readd;
++
++ INIT
++ wl_priv_signal_add(&signal.signal, &signal.l1);
++
++ signal.current = &signal.l1;
++ CHECK_EMIT(1)
++ CHECK_EMIT(1)
++
++ INIT
++ wl_priv_signal_add(&signal.signal, &signal.l1);
++
++ signal.current = &signal.l2;
++ CHECK_EMIT(1)
++ signal.current = NULL;
++ CHECK_EMIT(2)
++
++ INIT
++ wl_priv_signal_add(&signal.signal, &signal.l2);
++
++ signal.current = &signal.l1;
++ CHECK_EMIT(1)
++ /* l2 was added before l1, so l2 is fired first, which by readding l1
++ * removes it from the current list that is being fired, so 1 is correct */
++ CHECK_EMIT(1)
++
++ INIT
++ wl_priv_signal_add(&signal.signal, &signal.l1);
++ wl_priv_signal_add(&signal.signal, &signal.l2);
++
++ signal.l1.notify = notify_empty;
++ signal.current = &signal.l2;
++ CHECK_EMIT(2)
++ CHECK_EMIT(2)
++
++ INIT
++ wl_priv_signal_add(&signal.signal, &signal.l1);
++ wl_priv_signal_add(&signal.signal, &signal.l2);
++
++ signal.l1.notify = notify_empty;
++ signal.current = &signal.l1;
++ CHECK_EMIT(2)
++ /* same as before, by readding l1 in the first emit, it now is fired
++ * after l2, so on the second emit it is not fired at all. */
++ CHECK_EMIT(1)
++}
++
++static void notify_addandget(struct wl_listener *l, void *data)
++{
++ struct signal *signal = data;
++ wl_list_remove(&signal->current->link);
++ wl_list_init(&signal->current->link);
++ wl_priv_signal_add(&signal->signal, signal->current);
++
++ assert(wl_priv_signal_get(&signal->signal, signal->current->notify) != NULL);
++
++ signal->count++;
++}
++
++static void notify_get(struct wl_listener *l, void *data)
++{
++ struct signal *signal = data;
++ assert(wl_priv_signal_get(&signal->signal, signal->current->notify) == signal->current);
++ signal->count++;
++}
++
++TEST(signal_get_listener)
++{
++ test_set_timeout(4);
++
++ struct signal signal;
++
++ signal.l1.notify = notify_addandget;
++ signal.l2.notify = notify_get;
++
++ INIT
++ wl_priv_signal_add(&signal.signal, &signal.l1);
++
++ signal.current = &signal.l2;
++ CHECK_EMIT(1)
++
++ INIT
++ wl_priv_signal_add(&signal.signal, &signal.l2);
++
++ signal.current = &signal.l2;
++ CHECK_EMIT(1)
++
++ INIT
++ signal.l1.notify = notify_get;
++ signal.l2.notify = notify_empty;
++ wl_priv_signal_add(&signal.signal, &signal.l1);
++ wl_priv_signal_add(&signal.signal, &signal.l2);
++
++ CHECK_EMIT(2)
++
++ INIT
++ signal.l1.notify = notify_empty;
++ signal.l2.notify = notify_get;
++ wl_priv_signal_add(&signal.signal, &signal.l1);
++ wl_priv_signal_add(&signal.signal, &signal.l2);
++
++ signal.current = &signal.l1;
++ CHECK_EMIT(2)
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++#include "../config.h"
++
++#define _GNU_SOURCE
++
++#include <stdlib.h>
++#include <stdint.h>
++#include <assert.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <sys/stat.h>
++#include <unistd.h>
++#include <dlfcn.h>
++#include <errno.h>
++#include <stdarg.h>
++#include <fcntl.h>
++#include <stdio.h>
++#include <sys/epoll.h>
++
++#include "wayland-private.h"
++#include "test-runner.h"
++#include "wayland-os.h"
++
++static int fall_back;
++
++/* Play nice with sanitizers
++ *
++ * Sanitizers need to intercept syscalls in the compiler run-time library. As
++ * this isn't a separate ELF object, the usual dlsym(RTLD_NEXT) approach won't
++ * work: there can only be one function named "socket" etc. To support this, the
++ * sanitizer library names its interceptors with the prefix __interceptor_ ("__"
++ * being reserved for the implementation) and then weakly aliases it to the real
++ * function. The functions we define below will override the weak alias, and we
++ * can call them by the __interceptor_ name directly. This allows the sanitizer
++ * to do its work before calling the next version of the function via dlsym.
++ *
++ * However! We also don't know which of these functions the sanitizer actually
++ * wants to override, so we have to declare our own weak symbols for
++ * __interceptor_ and check at run time if they linked to anything or not.
++*/
++
++#define DECL(ret_type, func, ...) \
++ ret_type __interceptor_ ## func(__VA_ARGS__) __attribute__((weak)); \
++ static ret_type (*real_ ## func)(__VA_ARGS__); \
++ static int wrapped_calls_ ## func;
++
++#define REAL(func) (__interceptor_ ## func) ? \
++ __interceptor_ ## func : \
++ (__typeof__(&__interceptor_ ## func))dlsym(RTLD_NEXT, #func)
++
++DECL(int, socket, int, int, int);
++DECL(int, fcntl, int, int, ...);
++DECL(ssize_t, recvmsg, int, struct msghdr *, int);
++DECL(int, epoll_create1, int);
++
++static void
++init_fallbacks(int do_fallbacks)
++{
++ fall_back = do_fallbacks;
++ real_socket = REAL(socket);
++ real_fcntl = REAL(fcntl);
++ real_recvmsg = REAL(recvmsg);
++ real_epoll_create1 = REAL(epoll_create1);
++}
++
++__attribute__ ((visibility("default"))) int
++socket(int domain, int type, int protocol)
++{
++ wrapped_calls_socket++;
++
++ if (fall_back && (type & SOCK_CLOEXEC)) {
++ errno = EINVAL;
++ return -1;
++ }
++
++ return real_socket(domain, type, protocol);
++}
++
++__attribute__ ((visibility("default"))) int
++(fcntl)(int fd, int cmd, ...)
++{
++ va_list ap;
++ int arg;
++ int has_arg;
++
++ wrapped_calls_fcntl++;
++
++ if (fall_back && (cmd == F_DUPFD_CLOEXEC)) {
++ errno = EINVAL;
++ return -1;
++ }
++ switch (cmd) {
++ case F_DUPFD_CLOEXEC:
++ case F_DUPFD:
++ case F_SETFD:
++ va_start(ap, cmd);
++ arg = va_arg(ap, int);
++ has_arg = 1;
++ va_end(ap);
++ break;
++ case F_GETFD:
++ has_arg = 0;
++ break;
++ default:
++ fprintf(stderr, "Unexpected fctnl cmd %d\n", cmd);
++ abort();
++ }
++
++ if (has_arg) {
++ return real_fcntl(fd, cmd, arg);
++ }
++ return real_fcntl(fd, cmd);
++}
++
++__attribute__ ((visibility("default"))) ssize_t
++recvmsg(int sockfd, struct msghdr *msg, int flags)
++{
++ wrapped_calls_recvmsg++;
++
++ if (fall_back && (flags & MSG_CMSG_CLOEXEC)) {
++ errno = EINVAL;
++ return -1;
++ }
++
++ return real_recvmsg(sockfd, msg, flags);
++}
++
++__attribute__ ((visibility("default"))) int
++epoll_create1(int flags)
++{
++ wrapped_calls_epoll_create1++;
++
++ if (fall_back) {
++ wrapped_calls_epoll_create1++; /* epoll_create() not wrapped */
++ errno = EINVAL;
++ return -1;
++ }
++
++ return real_epoll_create1(flags);
++}
++
++static void
++do_os_wrappers_socket_cloexec(int n)
++{
++ int fd;
++ int nr_fds;
++
++ nr_fds = count_open_fds();
++
++ /* simply create a socket that closes on exec */
++ fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
++ assert(fd >= 0);
++
++ /*
++ * Must have 2 calls if falling back, but must also allow
++ * falling back without a forced fallback.
++ */
++ assert(wrapped_calls_socket > n);
++
++ exec_fd_leak_check(nr_fds);
++}
++
++TEST(os_wrappers_socket_cloexec)
++{
++ /* normal case */
++ init_fallbacks(0);
++ do_os_wrappers_socket_cloexec(0);
++}
++
++TEST(os_wrappers_socket_cloexec_fallback)
++{
++ /* forced fallback */
++ init_fallbacks(1);
++ do_os_wrappers_socket_cloexec(1);
++}
++
++static void
++do_os_wrappers_dupfd_cloexec(int n)
++{
++ int base_fd;
++ int fd;
++ int nr_fds;
++
++ nr_fds = count_open_fds();
++
++ base_fd = socket(PF_LOCAL, SOCK_STREAM, 0);
++ assert(base_fd >= 0);
++
++ fd = wl_os_dupfd_cloexec(base_fd, 13);
++ assert(fd >= 13);
++
++ close(base_fd);
++
++ /*
++ * Must have 4 calls if falling back, but must also allow
++ * falling back without a forced fallback.
++ */
++ assert(wrapped_calls_fcntl > n);
++
++ exec_fd_leak_check(nr_fds);
++}
++
++TEST(os_wrappers_dupfd_cloexec)
++{
++ init_fallbacks(0);
++ do_os_wrappers_dupfd_cloexec(0);
++}
++
++TEST(os_wrappers_dupfd_cloexec_fallback)
++{
++ init_fallbacks(1);
++ do_os_wrappers_dupfd_cloexec(3);
++}
++
++struct marshal_data {
++ struct wl_connection *read_connection;
++ struct wl_connection *write_connection;
++ int s[2];
++ uint32_t read_mask;
++ uint32_t write_mask;
++ union {
++ int h[3];
++ } value;
++ int nr_fds_begin;
++ int nr_fds_conn;
++ int wrapped_calls;
++};
++
++static void
++setup_marshal_data(struct marshal_data *data)
++{
++ assert(socketpair(AF_UNIX,
++ SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
++
++ data->read_connection = wl_connection_create(data->s[0]);
++ assert(data->read_connection);
++
++ data->write_connection = wl_connection_create(data->s[1]);
++ assert(data->write_connection);
++}
++
++static void
++marshal_demarshal(struct marshal_data *data,
++ void (*func)(void), int size, const char *format, ...)
++{
++ struct wl_closure *closure;
++ static const int opcode = 4444;
++ static struct wl_object sender = { NULL, NULL, 1234 };
++ struct wl_message message = { "test", format, NULL };
++ struct wl_map objects;
++ struct wl_object object = { NULL, &func, 1234 };
++ va_list ap;
++ uint32_t msg[1] = { 1234 };
++
++ va_start(ap, format);
++ closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
++ va_end(ap);
++
++ assert(closure);
++ assert(wl_closure_send(closure, data->write_connection) == 0);
++ wl_closure_destroy(closure);
++ assert(wl_connection_flush(data->write_connection) == size);
++
++ assert(wl_connection_read(data->read_connection) == size);
++
++ wl_map_init(&objects, WL_MAP_SERVER_SIDE);
++ object.id = msg[0];
++ closure = wl_connection_demarshal(data->read_connection,
++ size, &objects, &message);
++ assert(closure);
++ wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, &object, 0, data);
++ wl_closure_destroy(closure);
++}
++
++static void
++validate_recvmsg_h(struct marshal_data *data,
++ struct wl_object *object, int fd1, int fd2, int fd3)
++{
++ struct stat buf1, buf2;
++
++ assert(fd1 >= 0);
++ assert(fd2 >= 0);
++ assert(fd3 >= 0);
++
++ assert(fd1 != data->value.h[0]);
++ assert(fd2 != data->value.h[1]);
++ assert(fd3 != data->value.h[2]);
++
++ assert(fstat(fd3, &buf1) == 0);
++ assert(fstat(data->value.h[2], &buf2) == 0);
++ assert(buf1.st_dev == buf2.st_dev);
++ assert(buf1.st_ino == buf2.st_ino);
++
++ /* close the original file descriptors */
++ close(data->value.h[0]);
++ close(data->value.h[1]);
++ close(data->value.h[2]);
++
++ /* the dup'd (received) fds should still be open */
++ assert(count_open_fds() == data->nr_fds_conn + 3);
++
++ /*
++ * Must have 2 calls if falling back, but must also allow
++ * falling back without a forced fallback.
++ */
++ assert(wrapped_calls_recvmsg > data->wrapped_calls);
++
++ if (data->wrapped_calls == 0 && wrapped_calls_recvmsg > 1)
++ printf("recvmsg fell back unforced.\n");
++
++ /* all fds opened during the test in any way should be gone on exec */
++ exec_fd_leak_check(data->nr_fds_begin);
++}
++
++static void
++do_os_wrappers_recvmsg_cloexec(int n)
++{
++ struct marshal_data data;
++
++ data.nr_fds_begin = count_open_fds();
++#if HAVE_BROKEN_MSG_CMSG_CLOEXEC
++ /* We call the fallback directly on FreeBSD versions with a broken
++ * MSG_CMSG_CLOEXEC, so we don't call the local recvmsg() wrapper. */
++ data.wrapped_calls = 0;
++#else
++ data.wrapped_calls = n;
++#endif
++
++ setup_marshal_data(&data);
++ data.nr_fds_conn = count_open_fds();
++
++ assert(pipe(data.value.h) >= 0);
++
++ data.value.h[2] = open("/dev/zero", O_RDONLY);
++ assert(data.value.h[2] >= 0);
++
++ marshal_demarshal(&data, (void *) validate_recvmsg_h,
++ 8, "hhh", data.value.h[0], data.value.h[1],
++ data.value.h[2]);
++}
++
++TEST(os_wrappers_recvmsg_cloexec)
++{
++ init_fallbacks(0);
++ do_os_wrappers_recvmsg_cloexec(0);
++}
++
++TEST(os_wrappers_recvmsg_cloexec_fallback)
++{
++ init_fallbacks(1);
++ do_os_wrappers_recvmsg_cloexec(1);
++}
++
++static void
++do_os_wrappers_epoll_create_cloexec(int n)
++{
++ int fd;
++ int nr_fds;
++
++ nr_fds = count_open_fds();
++
++ fd = wl_os_epoll_create_cloexec();
++ assert(fd >= 0);
++
++#ifdef EPOLL_CLOEXEC
++ assert(wrapped_calls_epoll_create1 == n);
++#else
++ printf("No epoll_create1.\n");
++#endif
++
++ exec_fd_leak_check(nr_fds);
++}
++
++TEST(os_wrappers_epoll_create_cloexec)
++{
++ init_fallbacks(0);
++ do_os_wrappers_epoll_create_cloexec(1);
++}
++
++TEST(os_wrappers_epoll_create_cloexec_fallback)
++{
++ init_fallbacks(1);
++ do_os_wrappers_epoll_create_cloexec(2);
++}
++
++/* FIXME: add tests for wl_os_accept_cloexec() */
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <assert.h>
++#include <errno.h>
++#include <string.h>
++#include <stdio.h>
++#include <sys/un.h>
++#include <unistd.h>
++
++#include "wayland-client.h"
++#include "wayland-server.h"
++#include "test-runner.h"
++
++/* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */
++static const char *
++require_xdg_runtime_dir(void)
++{
++ char *val = getenv("XDG_RUNTIME_DIR");
++ assert(val && val[0] == '/' && "set $XDG_RUNTIME_DIR to run this test");
++
++ return val;
++}
++
++struct compositor {
++ struct wl_display *display;
++ struct wl_event_loop *loop;
++ int message;
++ struct wl_client *client;
++};
++
++struct message {
++ enum wl_protocol_logger_type type;
++ const char *class;
++ int opcode;
++ const char *message_name;
++ int args_count;
++} messages[] = {
++ {
++ .type = WL_PROTOCOL_LOGGER_REQUEST,
++ .class = "wl_display",
++ .opcode = 0,
++ .message_name = "sync",
++ .args_count = 1,
++ },
++ {
++ .type = WL_PROTOCOL_LOGGER_EVENT,
++ .class = "wl_callback",
++ .opcode = 0,
++ .message_name = "done",
++ .args_count = 1,
++ },
++ {
++ .type = WL_PROTOCOL_LOGGER_EVENT,
++ .class = "wl_display",
++ .opcode = 1,
++ .message_name = "delete_id",
++ .args_count = 1,
++ },
++};
++
++static void
++logger_func(void *user_data, enum wl_protocol_logger_type type,
++ const struct wl_protocol_logger_message *message)
++{
++ struct compositor *c = user_data;
++ struct message *msg = &messages[c->message++];
++
++ assert(msg->type == type);
++ assert(strcmp(msg->class, wl_resource_get_class(message->resource)) == 0);
++ assert(msg->opcode == message->message_opcode);
++ assert(strcmp(msg->message_name, message->message->name) == 0);
++ assert(msg->args_count == message->arguments_count);
++
++ c->client = wl_resource_get_client(message->resource);
++}
++
++static void
++callback_done(void *data, struct wl_callback *cb, uint32_t time)
++{
++ wl_callback_destroy(cb);
++}
++
++static const struct wl_callback_listener callback_listener = {
++ callback_done,
++};
++
++TEST(logger)
++{
++ test_set_timeout(1);
++
++ const char *socket;
++ struct compositor compositor = { 0 };
++ struct {
++ struct wl_display *display;
++ struct wl_callback *cb;
++ } client;
++ struct wl_protocol_logger *logger;
++
++ require_xdg_runtime_dir();
++
++ compositor.display = wl_display_create();
++ compositor.loop = wl_display_get_event_loop(compositor.display);
++ socket = wl_display_add_socket_auto(compositor.display);
++
++ logger = wl_display_add_protocol_logger(compositor.display,
++ logger_func, &compositor);
++
++ client.display = wl_display_connect(socket);
++ client.cb = wl_display_sync(client.display);
++ wl_callback_add_listener(client.cb, &callback_listener, NULL);
++ wl_display_flush(client.display);
++
++ while (compositor.message < 3) {
++ wl_event_loop_dispatch(compositor.loop, -1);
++ wl_display_flush_clients(compositor.display);
++ }
++
++ wl_display_dispatch(client.display);
++ wl_display_disconnect(client.display);
++
++ wl_client_destroy(compositor.client);
++ wl_protocol_logger_destroy(logger);
++ wl_display_destroy(compositor.display);
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright (c) 2019 Red Hat, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++#include <string.h>
++
++#include "wayland-server.h"
++#include "wayland-client.h"
++#include "test-runner.h"
++
++static struct {
++ struct wl_display *display;
++ struct wl_event_loop *loop;
++ int sync_count;
++} server;
++
++static struct {
++ struct wl_display *display;
++ struct wl_callback *callback_a;
++ struct wl_callback *callback_b;
++ int callback_count;
++} client;
++
++static const char *tag_a = "tag";
++static const char *tag_b = "tag";
++
++static void
++callback_done(void *data, struct wl_callback *cb, uint32_t time)
++{
++ const char * const *expected_tag;
++ const char * const *tag;
++
++ if (cb == client.callback_a)
++ expected_tag = &tag_a;
++ else if (cb == client.callback_b)
++ expected_tag = &tag_b;
++ else
++ assert(!"unexpected callback");
++
++ tag = wl_proxy_get_tag((struct wl_proxy *) cb);
++
++ assert(tag == expected_tag);
++ assert(strcmp(*tag, "tag") == 0);
++
++ wl_callback_destroy(cb);
++
++ client.callback_count++;
++}
++
++static const struct wl_callback_listener callback_listener = {
++ callback_done,
++};
++
++static void
++logger_func(void *user_data,
++ enum wl_protocol_logger_type type,
++ const struct wl_protocol_logger_message *message)
++{
++ if (type != WL_PROTOCOL_LOGGER_REQUEST)
++ return;
++
++ assert(strcmp(wl_resource_get_class(message->resource),
++ "wl_display") == 0);
++ assert(strcmp(message->message->name, "sync") == 0);
++
++ server.sync_count++;
++}
++
++TEST(proxy_tag)
++{
++ const char *socket;
++ struct wl_protocol_logger *logger;
++
++ assert(&tag_a != &tag_b);
++
++ server.display = wl_display_create();
++ assert(server.display);
++ server.loop = wl_display_get_event_loop(server.display);
++ assert(server.loop);
++ socket = wl_display_add_socket_auto(server.display);
++ assert(socket);
++ logger = wl_display_add_protocol_logger(server.display,
++ logger_func, NULL);
++ assert(logger);
++
++ client.display = wl_display_connect(socket);
++ assert(client.display);
++
++ client.callback_a = wl_display_sync(client.display);
++ wl_callback_add_listener(client.callback_a, &callback_listener, NULL);
++ wl_proxy_set_tag((struct wl_proxy *) client.callback_a,
++ &tag_a);
++
++ client.callback_b = wl_display_sync(client.display);
++ wl_callback_add_listener(client.callback_b, &callback_listener, NULL);
++ wl_proxy_set_tag((struct wl_proxy *) client.callback_b,
++ &tag_b);
++
++ wl_display_flush(client.display);
++
++ while (server.sync_count < 2) {
++ wl_event_loop_dispatch(server.loop, -1);
++ wl_display_flush_clients(server.display);
++ }
++
++ wl_display_dispatch(client.display);
++
++ assert(client.callback_count == 2);
++
++ wl_protocol_logger_destroy(logger);
++ wl_display_disconnect(client.display);
++ wl_event_loop_dispatch(server.loop, 100);
++
++ wl_display_destroy(server.display);
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Jonas Ådahl
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdbool.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <assert.h>
++
++#include "wayland-client.h"
++#include "wayland-server.h"
++#include "test-runner.h"
++#include "test-compositor.h"
++
++#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
++
++static void
++registry_handle_global(void *data, struct wl_registry *registry,
++ uint32_t id, const char *interface, uint32_t version)
++{
++ int *pcounter = data;
++ (*pcounter)++;
++ assert(*pcounter == 1);
++ wl_registry_destroy(registry);
++}
++
++static const struct wl_registry_listener registry_listener = {
++ registry_handle_global,
++ NULL
++};
++
++/* Test that destroying a proxy object doesn't result in any more
++ * callback being invoked, even though were many queued. */
++static void
++client_test_proxy_destroy(void)
++{
++ struct wl_display *display;
++ struct wl_registry *registry;
++ int counter = 0;
++
++ display = wl_display_connect(NULL);
++ assert(display);
++
++ registry = wl_display_get_registry(display);
++ assert(registry != NULL);
++ wl_registry_add_listener(registry, ®istry_listener,
++ &counter);
++ assert(wl_display_roundtrip(display) != -1);
++
++ assert(counter == 1);
++
++ /* don't destroy the registry, we have already destroyed them
++ * in the global handler */
++ wl_display_disconnect(display);
++}
++
++struct multiple_queues_state {
++ struct wl_display *display;
++ struct wl_callback* callback2;
++ bool done;
++};
++
++static void
++sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
++{
++ struct multiple_queues_state *state = data;
++
++ state->done = true;
++ wl_callback_destroy(callback);
++
++ wl_display_dispatch_pending(state->display);
++
++ wl_callback_destroy(state->callback2);
++}
++
++static const struct wl_callback_listener sync_listener = {
++ sync_callback
++};
++
++/* Test that when receiving the first of two synchronization
++ * callback events, destroying the second one doesn't cause any
++ * errors even if the delete_id event is handled out of order. */
++static void
++client_test_multiple_queues(void)
++{
++ struct wl_event_queue *queue;
++ struct wl_callback *callback1;
++ struct multiple_queues_state state;
++ int ret = 0;
++
++ state.display = wl_display_connect(NULL);
++ assert(state.display);
++
++ queue = wl_display_create_queue(state.display);
++ assert(queue);
++
++ state.done = false;
++ callback1 = wl_display_sync(state.display);
++ assert(callback1 != NULL);
++ wl_callback_add_listener(callback1, &sync_listener, &state);
++ wl_proxy_set_queue((struct wl_proxy *) callback1, queue);
++
++ state.callback2 = wl_display_sync(state.display);
++ assert(state.callback2 != NULL);
++ wl_callback_add_listener(state.callback2, &sync_listener, NULL);
++ wl_proxy_set_queue((struct wl_proxy *) state.callback2, queue);
++
++ wl_display_flush(state.display);
++
++ while (!state.done && !ret)
++ ret = wl_display_dispatch_queue(state.display, queue);
++
++ wl_event_queue_destroy(queue);
++ wl_display_disconnect(state.display);
++
++ exit(ret == -1 ? -1 : 0);
++}
++
++static void
++sync_callback_roundtrip(void *data, struct wl_callback *callback, uint32_t serial)
++{
++ bool *done = data;
++ *done = true;
++}
++
++static const struct wl_callback_listener sync_listener_roundtrip = {
++ sync_callback_roundtrip
++};
++
++/* Test that doing a roundtrip on a queue only the events on that
++ * queue get dispatched. */
++static void
++client_test_queue_roundtrip(void)
++{
++ struct wl_event_queue *queue;
++ struct wl_callback *callback1;
++ struct wl_callback *callback2;
++ struct wl_display *display;
++ bool done1 = false;
++ bool done2 = false;
++
++ display = wl_display_connect(NULL);
++ assert(display);
++
++ queue = wl_display_create_queue(display);
++ assert(queue);
++
++ /* arm a callback on the default queue */
++ callback1 = wl_display_sync(display);
++ assert(callback1 != NULL);
++ wl_callback_add_listener(callback1, &sync_listener_roundtrip, &done1);
++
++ /* arm a callback on the other queue */
++ callback2 = wl_display_sync(display);
++ assert(callback2 != NULL);
++ wl_callback_add_listener(callback2, &sync_listener_roundtrip, &done2);
++ wl_proxy_set_queue((struct wl_proxy *) callback2, queue);
++
++ /* roundtrip on default queue must not dispatch the other queue. */
++ wl_display_roundtrip(display);
++ assert(done1 == true);
++ assert(done2 == false);
++
++ /* re-arm the sync callback on the default queue, so we see that
++ * wl_display_roundtrip_queue() does not dispatch the default queue. */
++ wl_callback_destroy(callback1);
++ done1 = false;
++ callback1 = wl_display_sync(display);
++ assert(callback1 != NULL);
++ wl_callback_add_listener(callback1, &sync_listener_roundtrip, &done1);
++
++ wl_display_roundtrip_queue(display, queue);
++ assert(done1 == false);
++ assert(done2 == true);
++
++ wl_callback_destroy(callback1);
++ wl_callback_destroy(callback2);
++ wl_event_queue_destroy(queue);
++
++ wl_display_disconnect(display);
++}
++
++static void
++client_test_queue_proxy_wrapper(void)
++{
++ struct wl_event_queue *queue;
++ struct wl_display *display;
++ struct wl_display *display_wrapper;
++ struct wl_callback *callback;
++ bool done = false;
++
++ /*
++ * For an illustration of what usage would normally fail without using
++ * proxy wrappers, see the `client_test_queue_set_queue_race' test case.
++ */
++
++ display = wl_display_connect(NULL);
++ assert(display);
++
++ /* Pretend we are in a separate thread where a thread-local queue is
++ * used. */
++ queue = wl_display_create_queue(display);
++ assert(queue);
++
++ display_wrapper = wl_proxy_create_wrapper(display);
++ assert(display_wrapper);
++ wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue);
++ callback = wl_display_sync(display_wrapper);
++ wl_proxy_wrapper_destroy(display_wrapper);
++ assert(callback != NULL);
++
++ /* Pretend we are now another thread and dispatch the dispatch the main
++ * queue while also knowing our callback is read and queued. */
++ wl_display_roundtrip(display);
++
++ /* Make sure that the pretend-to-be main thread didn't dispatch our
++ * callback, behind our back. */
++ wl_callback_add_listener(callback, &sync_listener_roundtrip, &done);
++ wl_display_flush(display);
++
++ assert(!done);
++
++ /* Make sure that we eventually end up dispatching our callback. */
++ while (!done)
++ assert(wl_display_dispatch_queue(display, queue) != -1);
++
++ wl_callback_destroy(callback);
++ wl_event_queue_destroy(queue);
++
++ wl_display_disconnect(display);
++}
++
++static void
++client_test_queue_set_queue_race(void)
++{
++ struct wl_event_queue *queue;
++ struct wl_display *display;
++ struct wl_callback *callback;
++ bool done = false;
++
++ /*
++ * This test illustrates the multi threading scenario which would fail
++ * without doing what is done in the `client_test_queue_proxy_wrapper'
++ * test.
++ */
++
++ display = wl_display_connect(NULL);
++ assert(display);
++
++ /* Pretend we are in a separate thread where a thread-local queue is
++ * used. */
++ queue = wl_display_create_queue(display);
++ assert(queue);
++
++ callback = wl_display_sync(display);
++ assert(callback != NULL);
++
++ /* Pretend we are now another thread and dispatch the dispatch the main
++ * queue while also knowing our callback is read, queued on the wrong
++ * queue, and dispatched. */
++ wl_display_roundtrip(display);
++
++ /* Pretend we are back in the separate thread, and continue with setting
++ * up our callback. */
++ wl_callback_add_listener(callback, &sync_listener_roundtrip, &done);
++ wl_proxy_set_queue((struct wl_proxy *) callback, queue);
++
++ /* Roundtrip our separate thread queue to make sure any events are
++ * dispatched. */
++ wl_display_roundtrip_queue(display, queue);
++
++ /* Verify that the callback has indeed been dropped. */
++ assert(!done);
++
++ wl_callback_destroy(callback);
++ wl_event_queue_destroy(queue);
++
++ wl_display_disconnect(display);
++}
++
++static void
++dummy_bind(struct wl_client *client,
++ void *data, uint32_t version, uint32_t id)
++{
++}
++
++TEST(queue_proxy_destroy)
++{
++ struct display *d;
++ const struct wl_interface *dummy_interfaces[] = {
++ &wl_seat_interface,
++ &wl_pointer_interface,
++ &wl_keyboard_interface,
++ &wl_surface_interface
++ };
++ unsigned int i;
++
++ d = display_create();
++
++ for (i = 0; i < ARRAY_LENGTH(dummy_interfaces); i++)
++ wl_global_create(d->wl_display, dummy_interfaces[i],
++ dummy_interfaces[i]->version,
++ NULL, dummy_bind);
++
++ test_set_timeout(2);
++
++ client_create_noarg(d, client_test_proxy_destroy);
++ display_run(d);
++
++ display_destroy(d);
++}
++
++TEST(queue_multiple_queues)
++{
++ struct display *d = display_create();
++
++ test_set_timeout(2);
++
++ client_create_noarg(d, client_test_multiple_queues);
++ display_run(d);
++
++ display_destroy(d);
++}
++
++TEST(queue_roundtrip)
++{
++ struct display *d = display_create();
++
++ test_set_timeout(2);
++
++ client_create_noarg(d, client_test_queue_roundtrip);
++ display_run(d);
++
++ display_destroy(d);
++}
++
++TEST(queue_set_queue_proxy_wrapper)
++{
++ struct display *d = display_create();
++
++ test_set_timeout(2);
++
++ client_create_noarg(d, client_test_queue_proxy_wrapper);
++ display_run(d);
++
++ display_destroy(d);
++}
++
++TEST(queue_set_queue_race)
++{
++ struct display *d = display_create();
++
++ test_set_timeout(2);
++
++ client_create_noarg(d, client_test_queue_set_queue_race);
++ display_run(d);
++
++ display_destroy(d);
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2013 Marek Chalupa
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++#include <sys/socket.h>
++#include <unistd.h>
++#include <stdint.h>
++
++#include "wayland-server.h"
++#include "test-runner.h"
++
++TEST(create_resource_tst)
++{
++ struct wl_display *display;
++ struct wl_client *client;
++ struct wl_resource *res;
++ struct wl_list *link;
++ int s[2];
++ uint32_t id;
++
++ assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
++ display = wl_display_create();
++ assert(display);
++ client = wl_client_create(display, s[0]);
++ assert(client);
++
++ res = wl_resource_create(client, &wl_seat_interface, 4, 0);
++ assert(res);
++
++ /* setters/getters */
++ assert(wl_resource_get_version(res) == 4);
++
++ assert(client == wl_resource_get_client(res));
++ id = wl_resource_get_id(res);
++ assert(wl_client_get_object(client, id) == res);
++
++ link = wl_resource_get_link(res);
++ assert(link);
++ assert(wl_resource_from_link(link) == res);
++
++ wl_resource_set_user_data(res, (void *) 0xbee);
++ assert(wl_resource_get_user_data(res) == (void *) 0xbee);
++
++ wl_resource_destroy(res);
++ wl_client_destroy(client);
++ wl_display_destroy(display);
++ close(s[1]);
++}
++
++static void
++res_destroy_func(struct wl_resource *res)
++{
++ assert(res);
++
++ _Bool *destr = wl_resource_get_user_data(res);
++ *destr = 1;
++}
++
++static _Bool notify_called = 0;
++static void
++destroy_notify(struct wl_listener *l, void *data)
++{
++ assert(l && data);
++ notify_called = 1;
++
++ /* In real code it's common to free the structure holding the
++ * listener at this point, but not to remove it from the list.
++ *
++ * That's fine since this is a destruction notification and
++ * it's the last time this signal can fire. We set these
++ * to NULL so we can check them later to ensure no write after
++ * "free" occurred.
++ */
++ l->link.prev = NULL;
++ l->link.next = NULL;
++}
++
++TEST(destroy_res_tst)
++{
++ struct wl_display *display;
++ struct wl_client *client;
++ struct wl_resource *res;
++ int s[2];
++ unsigned id;
++ struct wl_list *link;
++
++ _Bool destroyed = 0;
++ struct wl_listener destroy_listener = {
++ .notify = &destroy_notify
++ };
++
++ assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
++ display = wl_display_create();
++ assert(display);
++ client = wl_client_create(display, s[0]);
++ assert(client);
++
++ res = wl_resource_create(client, &wl_seat_interface, 4, 0);
++ assert(res);
++ wl_resource_set_implementation(res, NULL, &destroyed, res_destroy_func);
++ wl_resource_add_destroy_listener(res, &destroy_listener);
++
++ id = wl_resource_get_id(res);
++ link = wl_resource_get_link(res);
++ assert(link);
++
++ wl_resource_destroy(res);
++ assert(destroyed);
++ assert(notify_called); /* check if signal was emitted */
++ assert(wl_client_get_object(client, id) == NULL);
++ assert(destroy_listener.link.prev == NULL);
++ assert(destroy_listener.link.next == NULL);
++
++ res = wl_resource_create(client, &wl_seat_interface, 2, 0);
++ assert(res);
++ destroyed = 0;
++ notify_called = 0;
++ wl_resource_set_destructor(res, res_destroy_func);
++ wl_resource_set_user_data(res, &destroyed);
++ wl_resource_add_destroy_listener(res, &destroy_listener);
++ /* client should destroy the resource upon its destruction */
++ wl_client_destroy(client);
++ assert(destroyed);
++ assert(notify_called);
++ assert(destroy_listener.link.prev == NULL);
++ assert(destroy_listener.link.next == NULL);
++
++ wl_display_destroy(display);
++ close(s[1]);
++}
++
++TEST(create_resource_with_same_id)
++{
++ struct wl_display *display;
++ struct wl_client *client;
++ struct wl_resource *res, *res2;
++ int s[2];
++ uint32_t id;
++
++ assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
++ display = wl_display_create();
++ assert(display);
++ client = wl_client_create(display, s[0]);
++ assert(client);
++
++ res = wl_resource_create(client, &wl_seat_interface, 2, 0);
++ assert(res);
++ id = wl_resource_get_id(res);
++ assert(wl_client_get_object(client, id) == res);
++
++ /* this one should replace the old one */
++ res2 = wl_resource_create(client, &wl_seat_interface, 1, id);
++ assert(res2 != NULL);
++ assert(wl_client_get_object(client, id) == res2);
++
++ wl_resource_destroy(res2);
++ wl_resource_destroy(res);
++
++ wl_client_destroy(client);
++ wl_display_destroy(display);
++ close(s[1]);
++}
++
++static void
++display_destroy_notify(struct wl_listener *l, void *data)
++{
++ l->link.prev = l->link.next = NULL;
++}
++
++TEST(free_without_remove)
++{
++ struct wl_display *display;
++ struct wl_listener a, b;
++
++ display = wl_display_create();
++ a.notify = display_destroy_notify;
++ b.notify = display_destroy_notify;
++
++ wl_display_add_destroy_listener(display, &a);
++ wl_display_add_destroy_listener(display, &b);
++
++ wl_display_destroy(display);
++
++ assert(a.link.next == a.link.prev && a.link.next == NULL);
++ assert(b.link.next == b.link.prev && b.link.next == NULL);
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <assert.h>
++#include <sys/types.h>
++#include <signal.h>
++#include <unistd.h>
++
++#include "test-runner.h"
++#include "wayland-util.h"
++#include "wayland-private.h"
++
++#include "test-compositor.h"
++
++extern int fd_leak_check_enabled;
++
++TEST(empty)
++{
++}
++
++TEST(exit_success)
++{
++ exit(EXIT_SUCCESS);
++}
++
++FAIL_TEST(exit_failure)
++{
++ exit(EXIT_FAILURE);
++}
++
++FAIL_TEST(fail_abort)
++{
++ test_disable_coredumps();
++ abort();
++}
++
++FAIL_TEST(fail_wl_abort)
++{
++ test_disable_coredumps();
++ wl_abort("Abort the program\n");
++}
++
++FAIL_TEST(fail_kill)
++{
++ kill(getpid(), SIGTERM);
++}
++
++FAIL_TEST(fail_segv)
++{
++ char * volatile *null = 0;
++
++ test_disable_coredumps();
++ *null = "Goodbye, world";
++}
++
++FAIL_TEST(sanity_assert)
++{
++ test_disable_coredumps();
++ /* must fail */
++ assert(0);
++}
++
++FAIL_TEST(sanity_fd_leak)
++{
++ int fd[2];
++
++ assert(fd_leak_check_enabled);
++
++ /* leak 2 file descriptors */
++ if (pipe(fd) < 0)
++ exit(EXIT_SUCCESS); /* failed to fail */
++
++ test_disable_coredumps();
++}
++
++FAIL_TEST(sanity_fd_leak_exec)
++{
++ int fd[2];
++ int nr_fds = count_open_fds();
++
++ /* leak 2 file descriptors */
++ if (pipe(fd) < 0)
++ exit(EXIT_SUCCESS); /* failed to fail */
++
++ test_disable_coredumps();
++ exec_fd_leak_check(nr_fds);
++}
++
++TEST(sanity_fd_exec)
++{
++ int fd[2];
++ int nr_fds = count_open_fds();
++
++ /* create 2 file descriptors, that should pass over exec */
++ assert(pipe(fd) >= 0);
++
++ exec_fd_leak_check(nr_fds + 2);
++}
++
++static void
++sanity_fd_no_leak(void)
++{
++ int fd[2];
++
++ assert(fd_leak_check_enabled);
++
++ /* leak 2 file descriptors */
++ if (pipe(fd) < 0)
++ exit(EXIT_SUCCESS); /* failed to fail */
++
++ close(fd[0]);
++ close(fd[1]);
++}
++
++static void
++sanity_client_no_leak(void)
++{
++ struct wl_display *display = wl_display_connect(NULL);
++ assert(display);
++
++ wl_display_disconnect(display);
++}
++
++TEST(tc_client_no_fd_leaks)
++{
++ struct display *d = display_create();
++
++ /* Client which does not consume the WAYLAND_DISPLAY socket. */
++ client_create_noarg(d, sanity_fd_no_leak);
++ display_run(d);
++
++ /* Client which does consume the WAYLAND_DISPLAY socket. */
++ client_create_noarg(d, sanity_client_no_leak);
++ display_run(d);
++
++ display_destroy(d);
++}
++
++FAIL_TEST(tc_client_fd_leaks)
++{
++ struct display *d = display_create();
++
++ client_create_noarg(d, sanity_fd_leak);
++ display_run(d);
++
++ test_disable_coredumps();
++ display_destroy(d);
++}
++
++FAIL_TEST(tc_client_fd_leaks_exec)
++{
++ struct display *d = display_create();
++
++ client_create_noarg(d, sanity_fd_leak_exec);
++ display_run(d);
++
++ test_disable_coredumps();
++ display_destroy(d);
++}
++
++FAIL_TEST(timeout_tst)
++{
++ test_set_timeout(1);
++ test_disable_coredumps();
++ /* test should reach timeout */
++ test_sleep(2);
++}
++
++TEST(timeout2_tst)
++{
++ /* the test should end before reaching timeout,
++ * thus it should pass */
++ test_set_timeout(1);
++ /* 200 000 microsec = 0.2 sec */
++ test_usleep(200000);
++}
++
++FAIL_TEST(timeout_reset_tst)
++{
++ test_set_timeout(5);
++ test_set_timeout(10);
++ test_set_timeout(1);
++
++ test_disable_coredumps();
++ /* test should fail on timeout */
++ test_sleep(2);
++}
++
++TEST(timeout_turnoff)
++{
++ test_set_timeout(1);
++ test_set_timeout(0);
++
++ test_usleep(2);
++}
++
++/* test timeouts with test-compositor */
++FAIL_TEST(tc_timeout_tst)
++{
++ struct display *d = display_create();
++ client_create_noarg(d, timeout_tst);
++ display_run(d);
++ test_disable_coredumps();
++ display_destroy(d);
++}
++
++FAIL_TEST(tc_timeout2_tst)
++{
++ struct display *d = display_create();
++ client_create_noarg(d, timeout_reset_tst);
++ display_run(d);
++ test_disable_coredumps();
++ display_destroy(d);
++}
++
++TEST(tc_timeout3_tst)
++{
++ struct display *d = display_create();
++
++ client_create_noarg(d, timeout2_tst);
++ display_run(d);
++
++ client_create_noarg(d, timeout_turnoff);
++ display_run(d);
++
++ display_destroy(d);
++}
--- /dev/null
--- /dev/null
++#!/bin/sh
++
++echo "srcdir: $srcdir"
++echo "scanner: $WAYLAND_SCANNER"
++echo "test_data_dir: $TEST_DATA_DIR"
++echo "test_output_dir: $TEST_OUTPUT_DIR"
++echo "pwd: $PWD"
++echo "sed: $SED"
++
++RETCODE=0
++
++hard_fail() {
++ echo "$@" "ERROR"
++ exit 99
++}
++
++fail() {
++ echo "$@" "FAIL"
++ RETCODE=1
++}
++
++mkdir -p "$TEST_OUTPUT_DIR" || hard_fail "setup"
++
++generate_and_compare() {
++ echo
++ echo "Testing $1 generation: $2 -> $3"
++
++ "$WAYLAND_SCANNER" $1 < "$TEST_DATA_DIR/$2" > "$TEST_OUTPUT_DIR/$3" || \
++ hard_fail "$2 -> $3"
++
++ "$SED" -i -e 's/Generated by wayland-scanner [0-9.]*/SCANNER TEST/' \
++ "$TEST_OUTPUT_DIR/$3" || hard_fail "$2 -> $3"
++
++ diff -q "$TEST_DATA_DIR/$3" "$TEST_OUTPUT_DIR/$3" && \
++ echo "$2 -> $3 PASS" || \
++ fail "$2 -> $3"
++}
++
++verify_error() {
++ echo
++ echo "Checking that reading $1 gives an error on line $3"
++
++ [ -f "$TEST_DATA_DIR/$1" ] || hard_fail "$1 not present"
++
++ # Confirm failure error code
++ "$WAYLAND_SCANNER" server-header < "$TEST_DATA_DIR/$1" >/dev/null 2>"$TEST_OUTPUT_DIR/$2" && \
++ fail "$1 return code check"
++
++ # Verify that an error is produced at the correct line
++ grep -q "<stdin>:$3: error:" "$TEST_OUTPUT_DIR/$2" && echo "$1 PASS" || fail "$1 line number check"
++}
++
++generate_and_compare "code" "example.xml" "example-code.c"
++generate_and_compare "client-header" "example.xml" "example-client.h"
++generate_and_compare "server-header" "example.xml" "example-server.h"
++
++generate_and_compare "code" "small.xml" "small-code.c"
++generate_and_compare "client-header" "small.xml" "small-client.h"
++generate_and_compare "server-header" "small.xml" "small-server.h"
++
++generate_and_compare "-c code" "small.xml" "small-code-core.c"
++generate_and_compare "-c client-header" "small.xml" "small-client-core.h"
++generate_and_compare "-c server-header" "small.xml" "small-server-core.h"
++
++# The existing "code" must produce result identical to "public-code"
++generate_and_compare "code" "small.xml" "small-code.c"
++generate_and_compare "public-code" "small.xml" "small-code.c"
++generate_and_compare "private-code" "small.xml" "small-private-code.c"
++
++verify_error "bad-identifier-arg.xml" "bad-identifier-arg.log" 7
++verify_error "bad-identifier-entry.xml" "bad-identifier-entry.log" 8
++verify_error "bad-identifier-enum.xml" "bad-identifier-enum.log" 6
++verify_error "bad-identifier-event.xml" "bad-identifier-event.log" 6
++verify_error "bad-identifier-interface.xml" "bad-identifier-interface.log" 3
++verify_error "bad-identifier-protocol.xml" "bad-identifier-protocol.log" 2
++verify_error "bad-identifier-request.xml" "bad-identifier-request.log" 6
++
++exit $RETCODE
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2013 Marek Chalupa
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++
++#include "wayland-server.h"
++#include "test-runner.h"
++
++static void
++signal_notify(struct wl_listener *listener, void *data)
++{
++ /* only increase counter*/
++ ++(*((int *) data));
++}
++
++TEST(signal_init)
++{
++ struct wl_signal signal;
++
++ wl_signal_init(&signal);
++
++ /* Test if listeners' list is initialized */
++ assert(&signal.listener_list == signal.listener_list.next
++ && "Maybe wl_signal implementation changed?");
++ assert(signal.listener_list.next == signal.listener_list.prev
++ && "Maybe wl_signal implementation changed?");
++}
++
++TEST(signal_add_get)
++{
++ struct wl_signal signal;
++
++ /* we just need different values of notify */
++ struct wl_listener l1 = {.notify = (wl_notify_func_t) 0x1};
++ struct wl_listener l2 = {.notify = (wl_notify_func_t) 0x2};
++ struct wl_listener l3 = {.notify = (wl_notify_func_t) 0x3};
++ /* one real, why not */
++ struct wl_listener l4 = {.notify = signal_notify};
++
++ wl_signal_init(&signal);
++
++ wl_signal_add(&signal, &l1);
++ wl_signal_add(&signal, &l2);
++ wl_signal_add(&signal, &l3);
++ wl_signal_add(&signal, &l4);
++
++ assert(wl_signal_get(&signal, signal_notify) == &l4);
++ assert(wl_signal_get(&signal, (wl_notify_func_t) 0x3) == &l3);
++ assert(wl_signal_get(&signal, (wl_notify_func_t) 0x2) == &l2);
++ assert(wl_signal_get(&signal, (wl_notify_func_t) 0x1) == &l1);
++
++ /* get should not be destructive */
++ assert(wl_signal_get(&signal, signal_notify) == &l4);
++ assert(wl_signal_get(&signal, (wl_notify_func_t) 0x3) == &l3);
++ assert(wl_signal_get(&signal, (wl_notify_func_t) 0x2) == &l2);
++ assert(wl_signal_get(&signal, (wl_notify_func_t) 0x1) == &l1);
++}
++
++TEST(signal_emit_to_one_listener)
++{
++ int count = 0;
++ int counter;
++
++ struct wl_signal signal;
++ struct wl_listener l1 = {.notify = signal_notify};
++
++ wl_signal_init(&signal);
++ wl_signal_add(&signal, &l1);
++
++ for (counter = 0; counter < 100; counter++)
++ wl_signal_emit(&signal, &count);
++
++ assert(counter == count);
++}
++
++TEST(signal_emit_to_more_listeners)
++{
++ int count = 0;
++ int counter;
++
++ struct wl_signal signal;
++ struct wl_listener l1 = {.notify = signal_notify};
++ struct wl_listener l2 = {.notify = signal_notify};
++ struct wl_listener l3 = {.notify = signal_notify};
++
++ wl_signal_init(&signal);
++ wl_signal_add(&signal, &l1);
++ wl_signal_add(&signal, &l2);
++ wl_signal_add(&signal, &l3);
++
++ for (counter = 0; counter < 100; counter++)
++ wl_signal_emit(&signal, &count);
++
++ assert(3 * counter == count);
++}
++
++struct signal_emit_mutable_data {
++ int count;
++ struct wl_listener *remove_listener;
++};
++
++static void
++signal_notify_mutable(struct wl_listener *listener, void *data)
++{
++ struct signal_emit_mutable_data *test_data = data;
++ test_data->count++;
++}
++
++static void
++signal_notify_and_remove_mutable(struct wl_listener *listener, void *data)
++{
++ struct signal_emit_mutable_data *test_data = data;
++ signal_notify_mutable(listener, test_data);
++ wl_list_remove(&test_data->remove_listener->link);
++}
++
++TEST(signal_emit_mutable)
++{
++ struct signal_emit_mutable_data data = {0};
++
++ /* l2 will remove l3 before l3 is notified */
++ struct wl_signal signal;
++ struct wl_listener l1 = {.notify = signal_notify_mutable};
++ struct wl_listener l2 = {.notify = signal_notify_and_remove_mutable};
++ struct wl_listener l3 = {.notify = signal_notify_mutable};
++
++ wl_signal_init(&signal);
++ wl_signal_add(&signal, &l1);
++ wl_signal_add(&signal, &l2);
++ wl_signal_add(&signal, &l3);
++
++ data.remove_listener = &l3;
++ wl_signal_emit_mutable(&signal, &data);
++
++ assert(data.count == 2);
++}
--- /dev/null
--- /dev/null
++/*
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <assert.h>
++#include <errno.h>
++#include <string.h>
++#include <stdio.h>
++#include <sys/socket.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <sys/un.h>
++#include <unistd.h>
++
++#include "wayland-client.h"
++#include "wayland-os.h"
++#include "wayland-server.h"
++#include "test-runner.h"
++
++/* Paths longer than what the .sun_path array can contain must be rejected.
++ * This is a hard limitation of assigning a name to AF_UNIX/AF_LOCAL sockets.
++ * See `man 7 unix`.
++ */
++
++static struct sockaddr_un example_sockaddr_un;
++
++#define TOO_LONG (1 + sizeof example_sockaddr_un.sun_path)
++
++/* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */
++static const char *
++require_xdg_runtime_dir(void)
++{
++ char *val = getenv("XDG_RUNTIME_DIR");
++ assert(val && val[0] == '/' && "set $XDG_RUNTIME_DIR to run this test");
++
++ return val;
++}
++
++TEST(socket_path_overflow_client_connect)
++{
++ char path[TOO_LONG];
++ struct wl_display *d;
++
++ require_xdg_runtime_dir();
++
++ memset(path, 'a', sizeof path);
++ path[sizeof path - 1] = '\0';
++
++ d = wl_display_connect(path);
++ assert(d == NULL);
++ assert(errno == ENAMETOOLONG);
++
++ /* This is useless, but prevents a warning about example_sockaddr_un
++ * being discarded from the compilation unit. */
++ strcpy(example_sockaddr_un.sun_path, "happy now clang?");
++ assert(example_sockaddr_un.sun_path[0] != '\0');
++}
++
++TEST(socket_path_overflow_server_create)
++{
++ char path[TOO_LONG];
++ struct wl_display *d;
++ int ret;
++
++ require_xdg_runtime_dir();
++
++ memset(path, 'a', sizeof path);
++ path[sizeof path - 1] = '\0';
++
++ d = wl_display_create();
++ assert(d != NULL);
++
++ ret = wl_display_add_socket(d, path);
++ assert(ret < 0);
++ assert(errno == ENAMETOOLONG);
++
++ wl_display_destroy(d);
++}
++
++TEST(add_existing_socket)
++{
++ char path[sizeof example_sockaddr_un.sun_path];
++ const char *name = "wayland-test-0";
++ const char *xdg_runtime_dir;
++ struct wl_display *d;
++ int ret;
++ size_t len;
++
++ xdg_runtime_dir = require_xdg_runtime_dir();
++
++ d = wl_display_create();
++ assert(d != NULL);
++
++ /* this one should be OK */
++ ret = wl_display_add_socket(d, name);
++ assert(ret == 0);
++
++ /* this one should fail */
++ ret = wl_display_add_socket(d, name);
++ assert(ret < 0);
++
++ /* the original socket should still exist.
++ * this was a bug introduced in e2c0d47b0c77f18cd90e9c6eabb358c4d89681c8 */
++ len = snprintf(path, sizeof example_sockaddr_un.sun_path, "%s/%s",
++ xdg_runtime_dir, name);
++ assert(len < sizeof example_sockaddr_un.sun_path
++ && "Bug in test. Path too long");
++
++ assert(access(path, F_OK) != -1);
++
++ /* the original socket should still exist */
++ ret = wl_display_add_socket(d, name);
++ assert(ret < 0);
++
++ wl_display_destroy(d);
++}
++
++TEST(add_socket_auto)
++{
++ /* the number of auto sockets is currently 32,
++ * set in wayland-server.c.
++ */
++ const int MAX_SOCKETS = 32;
++
++ char path[sizeof example_sockaddr_un.sun_path];
++ const char *name;
++ const char *xdg_runtime_dir;
++ struct wl_display *d;
++ int i;
++ size_t len;
++
++ xdg_runtime_dir = require_xdg_runtime_dir();
++
++ d = wl_display_create();
++ assert(d != NULL);
++
++ for (i = 0; i <= MAX_SOCKETS; ++i) {
++ name = wl_display_add_socket_auto(d);
++ assert(name != NULL);
++
++ len = snprintf(path, sizeof example_sockaddr_un.sun_path,
++ "%s/%s", xdg_runtime_dir, name);
++ assert(len < sizeof example_sockaddr_un.sun_path
++ && "Bug in test. Path too long");
++
++ /* was the socket created correctly? */
++ assert(access(path, F_OK) != -1);
++
++ /* is the name sequential? */
++ len = snprintf(path, sizeof example_sockaddr_un.sun_path,
++ "wayland-%d", i);
++ assert(strcmp(name, path) == 0);
++ }
++
++ /* next addition should return NULL */
++ name = wl_display_add_socket_auto(d);
++ assert(name == NULL);
++
++ /* check if the socket was not deleted the last time */
++ name = wl_display_add_socket_auto(d);
++ assert(name == NULL);
++
++ wl_display_destroy(d);
++}
++
++struct client_create_listener {
++ struct wl_listener listener;
++ struct wl_display *display;
++};
++
++struct client_destroy_listener {
++ struct wl_listener listener;
++ struct wl_display *display;
++};
++
++static void
++client_destroy_notify(struct wl_listener *l, void *data)
++{
++ struct client_destroy_listener *listener =
++ wl_container_of(l, listener, listener);
++ wl_display_terminate(listener->display);
++ free(listener);
++}
++
++static void
++client_create_notify(struct wl_listener *l, void *data)
++{
++ struct wl_client *client = data;
++ struct client_create_listener *listener =
++ wl_container_of(l, listener, listener);
++ struct client_destroy_listener *destroy_listener = (struct client_destroy_listener *)malloc(sizeof *destroy_listener);
++ assert(destroy_listener != NULL);
++ destroy_listener->display = listener->display;
++ destroy_listener->listener.notify = client_destroy_notify;
++ wl_client_add_destroy_listener(client, &destroy_listener->listener);
++}
++
++TEST(absolute_socket_path)
++{
++ struct wl_display *display;
++ struct client_create_listener client_create_listener;
++ struct sockaddr_un addr;
++ int fd;
++ socklen_t size;
++ const char *xdg_runtime_dir;
++ size_t len;
++ int ret;
++ pid_t pid;
++
++ /* It's a little weird that this test about absolute socket paths
++ * uses XDG_RUNTIME_DIR, but that's the only location guaranteed
++ * by test-runner to be both writable and unique. This isn't
++ * really a problem; we'll just take care that the leaf-level
++ * filename used for the socket isn't anything that would
++ * accidentally be generated by a default usage of wl_display_connect(). */
++ xdg_runtime_dir = require_xdg_runtime_dir();
++ memset(&addr, 0, sizeof addr);
++ len = snprintf(addr.sun_path, sizeof addr.sun_path,
++ "%s/%s", xdg_runtime_dir, "wayland-absolute-0");
++ assert(len < sizeof addr.sun_path
++ && "Bug in test. Path too long");
++
++ /* The path must not exist prior to binding. */
++ assert(access(addr.sun_path, F_OK) == -1);
++
++ size = offsetof (struct sockaddr_un, sun_path) + strlen(addr.sun_path);
++ addr.sun_family = AF_LOCAL;
++ fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
++ assert(fd >= 0 );
++ ret = bind(fd, (struct sockaddr *) &addr, size);
++ assert(ret >= 0);
++ ret = listen(fd, 128);
++ assert(ret >= 0);
++
++ /* Start server display. Be careful (by avoiding wl_display_add_socket_auto()
++ * to offer only the absolutely qualified socket made above. */
++ display = wl_display_create();
++ assert(display != NULL);
++ client_create_listener.listener.notify = client_create_notify;
++ client_create_listener.display = display;
++ wl_display_add_client_created_listener(display, &client_create_listener.listener);
++ ret = wl_display_add_socket_fd(display, fd);
++ assert(ret == 0);
++
++ /* Execute client that connects to the absolutely qualified server socket path. */
++ pid = fork();
++ assert(pid != -1);
++
++ if (pid == 0) {
++ ret = setenv("WAYLAND_DISPLAY", addr.sun_path, 1);
++ assert(ret == 0);
++ struct wl_display *client_display = wl_display_connect(NULL);
++ assert(client_display != NULL);
++ ret = wl_display_roundtrip(client_display);
++ assert(ret != -1);
++ wl_display_disconnect(client_display);
++ exit(0);
++ assert(false);
++ }
++
++ wl_display_run(display);
++ ret = waitpid(pid, NULL, 0);
++ assert(ret == pid);
++
++ wl_display_destroy(display);
++
++ ret = unlink(addr.sun_path);
++ assert(ret == 0);
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright (c) 2014 Red Hat, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++#include <errno.h>
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <unistd.h>
++#include <sys/time.h>
++#include <sys/socket.h>
++#include <sys/wait.h>
++#include <signal.h>
++
++#define WL_HIDE_DEPRECATED
++
++#include "test-runner.h"
++#include "test-compositor.h"
++
++/* --- Protocol --- */
++struct test_compositor;
++
++static const struct wl_message tc_requests[] = {
++ /* this request serves as a barrier for synchronizing*/
++ { "stop_display", "u", NULL },
++ { "noop", "", NULL },
++};
++
++static const struct wl_message tc_events[] = {
++ { "display_resumed", "", NULL }
++};
++
++const struct wl_interface test_compositor_interface = {
++ "test", 1,
++ 2, tc_requests,
++ 1, tc_events
++};
++
++struct test_compositor_interface {
++ void (*stop_display)(struct wl_client *client,
++ struct wl_resource *resource,
++ uint32_t num);
++ void (*noop)(struct wl_client *client,
++ struct wl_resource *resource);
++};
++
++struct test_compositor_listener {
++ void (*display_resumed)(void *data, struct test_compositor *tc);
++
++};
++
++enum {
++ STOP_DISPLAY = 0,
++ TEST_NOOP = 1
++};
++
++enum {
++ DISPLAY_RESUMED = 0
++};
++
++/* Since tests can run parallelly, we need unique socket names
++ * for each test, otherwise the test can fail on wl_display_add_socket. */
++static const char *
++get_socket_name(void)
++{
++ struct timeval tv;
++ static char retval[64];
++
++ gettimeofday(&tv, NULL);
++ snprintf(retval, sizeof retval, "wayland-test-%d-%ld%ld",
++ getpid(), tv.tv_sec, tv.tv_usec);
++
++ return retval;
++}
++
++static void
++handle_client_destroy(void *data)
++{
++ struct client_info *ci = data;
++ struct display *d;
++ siginfo_t status;
++
++ d = ci->display;
++
++ assert(waitid(P_PID, ci->pid, &status, WEXITED) != -1);
++
++ switch (status.si_code) {
++ case CLD_KILLED:
++ case CLD_DUMPED:
++ fprintf(stderr, "Client '%s' was killed by signal %d\n",
++ ci->name, status.si_status);
++ ci->exit_code = status.si_status;
++ break;
++ case CLD_EXITED:
++ if (status.si_status != EXIT_SUCCESS)
++ fprintf(stderr, "Client '%s' exited with code %d\n",
++ ci->name, status.si_status);
++
++ ci->exit_code = status.si_status;
++ break;
++ }
++
++ ++d->clients_terminated_no;
++ if (d->clients_no == d->clients_terminated_no) {
++ wl_display_terminate(d->wl_display);
++ }
++
++ /* the clients are not removed from the list, because
++ * at the end of the test we check the exit codes of all
++ * clients. In the case that the test would go through
++ * the clients list manually, zero out the wl_client as a sign
++ * that the client is not running anymore */
++}
++
++/**
++ * Check client's state and terminate display when all clients exited
++ */
++static void
++client_destroyed(struct wl_listener *listener, void *data)
++{
++ struct client_info *ci;
++ struct display *d;
++ struct wl_event_loop *loop;
++
++ /* Wait for client in an idle handler to avoid blocking the actual
++ * client destruction (fd close etc. */
++ ci = wl_container_of(listener, ci, destroy_listener);
++ d = ci->display;
++ loop = wl_display_get_event_loop(d->wl_display);
++ wl_event_loop_add_idle(loop, handle_client_destroy, ci);
++
++ ci->wl_client = NULL;
++}
++
++static void
++run_client(void (*client_main)(void *data), void *data,
++ int wayland_sock, int client_pipe)
++{
++ char s[8];
++ int cur_fds;
++ int can_continue = 0;
++
++ /* Wait until display signals that client can continue */
++ assert(read(client_pipe, &can_continue, sizeof(int)) == sizeof(int));
++
++ if (can_continue == 0)
++ abort(); /* error in parent */
++
++ /* for wl_display_connect() */
++ snprintf(s, sizeof s, "%d", wayland_sock);
++ setenv("WAYLAND_SOCKET", s, 0);
++
++ cur_fds = count_open_fds();
++
++ client_main(data);
++
++ /* Clients using wl_display_connect() will end up closing the socket
++ * passed in through the WAYLAND_SOCKET environment variable. When
++ * doing this, it clears the environment variable, so if it's been
++ * unset, then we assume the client consumed the file descriptor and
++ * do not count it towards leak checking. */
++ if (!getenv("WAYLAND_SOCKET"))
++ cur_fds--;
++
++ check_fd_leaks(cur_fds);
++}
++
++static struct client_info *
++display_create_client(struct display *d,
++ void (*client_main)(void *data),
++ void *data,
++ const char *name)
++{
++ int pipe_cli[2];
++ int sock_wayl[2];
++ pid_t pid;
++ int can_continue = 0;
++ struct client_info *cl;
++
++ assert(pipe(pipe_cli) == 0 && "Failed creating pipe");
++ assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_wayl) == 0
++ && "Failed creating socket pair");
++
++ pid = fork();
++ assert(pid != -1 && "Fork failed");
++
++ if (pid == 0) {
++ close(sock_wayl[1]);
++ close(pipe_cli[1]);
++
++ run_client(client_main, data, sock_wayl[0], pipe_cli[0]);
++
++ close(sock_wayl[0]);
++ close(pipe_cli[0]);
++
++ exit(0);
++ }
++
++ close(sock_wayl[0]);
++ close(pipe_cli[0]);
++
++ cl = calloc(1, sizeof(struct client_info));
++ assert(cl && "Out of memory");
++
++ wl_list_insert(&d->clients, &cl->link);
++
++ cl->display = d;
++ cl->name = name;
++ cl->pid = pid;
++ cl->pipe = pipe_cli[1];
++ cl->destroy_listener.notify = &client_destroyed;
++
++ cl->wl_client = wl_client_create(d->wl_display, sock_wayl[1]);
++ if (!cl->wl_client) {
++ int ret;
++
++ /* abort the client */
++ ret = write(cl->pipe, &can_continue, sizeof(int));
++ assert(ret == sizeof(int) && "aborting the client failed");
++ assert(0 && "Couldn't create wayland client");
++ }
++
++ wl_client_add_destroy_listener(cl->wl_client,
++ &cl->destroy_listener);
++
++ ++d->clients_no;
++
++ return cl;
++}
++
++struct client_info *
++client_create_with_name(struct display *d,
++ void (*client_main)(void *data), void *data,
++ const char *name)
++{
++ int can_continue = 1;
++ struct client_info *cl = display_create_client(d,
++ client_main, data,
++ name);
++
++ /* let the show begin! */
++ assert(write(cl->pipe, &can_continue, sizeof(int)) == sizeof(int));
++
++ return cl;
++}
++
++/* wfr = waiting for resume */
++struct wfr {
++ struct wl_resource *resource;
++ struct wl_list link;
++};
++
++static void
++handle_stop_display(struct wl_client *client,
++ struct wl_resource *resource, uint32_t num)
++{
++ struct display *d = wl_resource_get_user_data(resource);
++ struct wfr *wfr;
++
++ assert(d->wfr_num < num
++ && "test error: Too many clients sent stop_display request");
++
++ ++d->wfr_num;
++
++ wfr = malloc(sizeof *wfr);
++ if (!wfr) {
++ wl_client_post_no_memory(client);
++ assert(0 && "Out of memory");
++ }
++
++ wfr->resource = resource;
++ wl_list_insert(&d->waiting_for_resume, &wfr->link);
++
++ if (d->wfr_num == num)
++ wl_display_terminate(d->wl_display);
++}
++
++static void
++handle_noop(struct wl_client *client, struct wl_resource *resource)
++{
++ (void)client;
++ (void)resource;
++}
++
++static const struct test_compositor_interface tc_implementation = {
++ handle_stop_display,
++ handle_noop,
++};
++
++static void
++tc_bind(struct wl_client *client, void *data,
++ uint32_t ver, uint32_t id)
++{
++ struct wl_resource *res;
++
++ res = wl_resource_create(client, &test_compositor_interface, ver, id);
++ if (!res) {
++ wl_client_post_no_memory(client);
++ assert(0 && "Out of memory");
++ }
++
++ wl_resource_set_implementation(res, &tc_implementation, data, NULL);
++}
++
++struct display *
++display_create(void)
++{
++ struct display *d = NULL;
++ const char *socket_name;
++ int stat = 0;
++
++ d = calloc(1, sizeof *d);
++ assert(d && "Out of memory");
++
++ d->wl_display = wl_display_create();
++ assert(d->wl_display && "Creating display failed");
++
++ /* hope the path won't be longer than 108 ... */
++ socket_name = get_socket_name();
++ stat = wl_display_add_socket(d->wl_display, socket_name);
++ assert(stat == 0 && "Failed adding socket");
++
++ wl_list_init(&d->clients);
++ d->clients_no = d->clients_terminated_no = 0;
++
++ wl_list_init(&d->waiting_for_resume);
++ d->wfr_num = 0;
++
++ d->test_global = wl_global_create(d->wl_display,
++ &test_compositor_interface,
++ 1, d, tc_bind);
++ assert(d->test_global && "Creating test global failed");
++
++ return d;
++}
++
++void
++display_run(struct display *d)
++{
++ assert(d->wfr_num == 0
++ && "test error: Have waiting clients. Use display_resume.");
++ wl_display_run(d->wl_display);
++}
++
++void
++display_post_resume_events(struct display *d)
++{
++ struct wfr *wfr, *next;
++
++ assert(d->wfr_num > 0 && "test error: No clients waiting.");
++
++ wl_list_for_each_safe(wfr, next, &d->waiting_for_resume, link) {
++ wl_resource_post_event(wfr->resource, DISPLAY_RESUMED);
++ wl_list_remove(&wfr->link);
++ free(wfr);
++ }
++
++ assert(wl_list_empty(&d->waiting_for_resume));
++ d->wfr_num = 0;
++}
++
++void
++display_resume(struct display *d)
++{
++ display_post_resume_events(d);
++ wl_display_run(d->wl_display);
++}
++
++void
++display_destroy(struct display *d)
++{
++ struct client_info *cl, *next;
++ int failed = 0;
++
++ assert(d->wfr_num == 0
++ && "test error: Didn't you forget to call display_resume?");
++
++ wl_list_for_each_safe(cl, next, &d->clients, link) {
++ assert(cl->wl_client == NULL);
++
++ if (cl->exit_code != 0) {
++ ++failed;
++ fprintf(stderr, "Client '%s' failed\n", cl->name);
++ }
++
++ close(cl->pipe);
++ free(cl);
++ }
++
++ wl_global_destroy(d->test_global);
++ wl_display_destroy(d->wl_display);
++ free(d);
++
++ if (failed) {
++ fprintf(stderr, "%d child(ren) failed\n", failed);
++ abort();
++ }
++}
++
++/*
++ * --- Client helper functions ---
++ */
++static void
++handle_display_resumed(void *data, struct test_compositor *tc)
++{
++ struct client *c = data;
++
++ c->display_stopped = 0;
++}
++
++static const struct test_compositor_listener tc_listener = {
++ handle_display_resumed
++};
++
++static void
++registry_handle_globals(void *data, struct wl_registry *registry,
++ uint32_t id, const char *intf, uint32_t ver)
++{
++ struct client *c = data;
++
++ if (strcmp(intf, "test") != 0)
++ return;
++
++ c->tc = wl_registry_bind(registry, id, &test_compositor_interface, ver);
++ assert(c->tc && "Failed binding to registry");
++
++ wl_proxy_add_listener((struct wl_proxy *) c->tc,
++ (void *) &tc_listener, c);
++}
++
++static const struct wl_registry_listener registry_listener =
++{
++ registry_handle_globals,
++ NULL
++};
++
++struct client *client_connect()
++{
++ struct wl_registry *reg;
++ struct client *c = calloc(1, sizeof *c);
++ assert(c && "Out of memory");
++
++ c->wl_display = wl_display_connect(NULL);
++ assert(c->wl_display && "Failed connecting to display");
++
++ /* create test_compositor proxy. Do it with temporary
++ * registry so that client can define it's own listener later */
++ reg = wl_display_get_registry(c->wl_display);
++ assert(reg);
++ wl_registry_add_listener(reg, ®istry_listener, c);
++ wl_display_roundtrip(c->wl_display);
++ assert(c->tc);
++
++ wl_registry_destroy(reg);
++
++ return c;
++}
++
++static void
++check_error(struct wl_display *display)
++{
++ uint32_t ec, id;
++ const struct wl_interface *intf;
++ int err;
++
++ err = wl_display_get_error(display);
++ /* write out message about protocol error */
++ if (err == EPROTO) {
++ ec = wl_display_get_protocol_error(display, &intf, &id);
++ fprintf(stderr, "Client: Got protocol error %u on interface %s"
++ " (object %u)\n", ec, intf->name, id);
++ }
++
++ if (err) {
++ fprintf(stderr, "Client error: %s\n", strerror(err));
++ abort();
++ }
++}
++
++void
++client_disconnect(struct client *c)
++{
++ /* check for errors */
++ check_error(c->wl_display);
++
++ wl_proxy_destroy((struct wl_proxy *) c->tc);
++ wl_display_disconnect(c->wl_display);
++ free(c);
++}
++
++/* num is number of clients that requests to stop display.
++ * Display is stopped after it receives num STOP_DISPLAY requests */
++int
++stop_display(struct client *c, int num)
++{
++ int n = 0;
++
++ c->display_stopped = 1;
++ wl_proxy_marshal((struct wl_proxy *) c->tc, STOP_DISPLAY, num);
++
++ while (c->display_stopped && n >= 0) {
++ n = wl_display_dispatch(c->wl_display);
++ }
++
++ return n;
++}
++
++void
++noop_request(struct client *c)
++{
++ wl_proxy_marshal((struct wl_proxy *) c->tc, TEST_NOOP);
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright (c) 2014 Red Hat, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdint.h>
++#include <unistd.h>
++#include <stdatomic.h>
++
++#include "wayland-server.h"
++#include "wayland-client.h"
++
++/* info about a client on server side */
++struct client_info {
++ struct display *display;
++ struct wl_client *wl_client;
++ struct wl_listener destroy_listener;
++ const char *name; /* for debugging */
++
++ int pipe;
++ pid_t pid;
++ int exit_code;
++
++ struct wl_list link;
++ void *data; /* for arbitrary use */
++};
++
++struct display {
++ struct wl_display *wl_display;
++ struct wl_global *test_global;
++
++ struct wl_list clients;
++ uint32_t clients_no;
++ uint32_t clients_terminated_no;
++
++ /* list of clients waiting for display_resumed event */
++ struct wl_list waiting_for_resume;
++ uint32_t wfr_num;
++};
++
++/* This is a helper structure for clients.
++ * Instead of calling wl_display_connect() and all the other stuff,
++ * client can use client_connect and it will return this structure
++ * filled. */
++struct client {
++ struct wl_display *wl_display;
++ struct test_compositor *tc;
++
++ atomic_bool display_stopped;
++};
++
++struct client *client_connect(void);
++void client_disconnect(struct client *);
++int stop_display(struct client *, int);
++void noop_request(struct client *);
++
++/**
++ * Usual workflow:
++ *
++ * d = display_create();
++ *
++ * wl_global_create(d->wl_display, ...);
++ * ... other setups ...
++ *
++ * client_create(d, client_main, data);
++ * client_create(d, client_main2, data);
++ *
++ * display_run(d);
++ * display_destroy(d);
++ */
++struct display *display_create(void);
++void display_destroy(struct display *d);
++void display_run(struct display *d);
++
++/* This function posts the display_resumed event to all waiting clients,
++ * so that after flushing events the clients will stop waiting and continue.
++ *
++ * (Calling `display_run` after this function will resume the display loop.)
++ */
++void display_post_resume_events(struct display *d);
++/* After n clients called stop_display(..., n), the display
++ * is stopped and can process the code after display_run().
++ *
++ * This function posts the display_resumed event to the waiting
++ * clients, so that the clients will stop waiting and continue;
++ * it then reruns the display. */
++void display_resume(struct display *d);
++
++
++struct client_info *client_create_with_name(struct display *d,
++ void (*client_main)(void *data),
++ void *data,
++ const char *name);
++#define client_create(d, c, data) client_create_with_name((d), (c), data, (#c))
++#define client_create_noarg(d, c) \
++ client_create_with_name((d), (void(*)(void *)) (c), NULL, (#c))
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "config.h"
++
++#include <assert.h>
++#include <errno.h>
++#include <dirent.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <time.h>
++#include <sys/time.h>
++#include <sys/resource.h>
++
++#ifdef HAVE_SYS_PRCTL_H
++#include <sys/prctl.h>
++#endif
++
++#include "test-runner.h"
++
++#if defined(__FreeBSD__)
++#include <sys/sysctl.h>
++
++/*
++ * On FreeBSD, get file descriptor information using sysctl() since that does
++ * not depend on a mounted fdescfs (which provides /dev/fd/N for N > 2).
++ */
++int
++count_open_fds(void)
++{
++ int error;
++ int nfds;
++ int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_NFDS, 0 };
++ size_t len;
++
++ len = sizeof(nfds);
++ error = sysctl(mib, 4, &nfds, &len, NULL, 0);
++ assert(error == 0 && "sysctl KERN_PROC_NFDS failed.");
++ return nfds;
++}
++#else
++int
++count_open_fds(void)
++{
++ DIR *dir;
++ struct dirent *ent;
++ int count = 0;
++
++ /*
++ * Using /dev/fd instead of /proc/self/fd should allow this code to
++ * work on non-Linux operating systems.
++ */
++ dir = opendir("/dev/fd");
++ assert(dir && "opening /dev/fd failed.");
++
++ errno = 0;
++ while ((ent = readdir(dir))) {
++ const char *s = ent->d_name;
++ if (s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
++ continue;
++ count++;
++ }
++ assert(errno == 0 && "reading /dev/fd failed.");
++
++ closedir(dir);
++
++ return count;
++}
++#endif
++
++void
++exec_fd_leak_check(int nr_expected_fds)
++{
++ const char *exe = "exec-fd-leak-checker";
++ char number[16] = { 0 };
++ const char *test_build_dir = getenv("TEST_BUILD_DIR");
++ char exe_path[256] = { 0 };
++
++ if (test_build_dir == NULL || test_build_dir[0] == 0) {
++ test_build_dir = ".";
++ }
++
++ snprintf(exe_path, sizeof exe_path - 1, "%s/%s", test_build_dir, exe);
++
++ snprintf(number, sizeof number - 1, "%d", nr_expected_fds);
++ execl(exe_path, exe, number, (char *)NULL);
++ assert(0 && "execing fd leak checker failed");
++}
++
++#define USEC_TO_NSEC(n) (1000 * (n))
++
++/* our implementation of usleep and sleep functions that are safe to use with
++ * timeouts (timeouts are implemented using alarm(), so it is not safe use
++ * usleep and sleep. See man pages of these functions)
++ */
++void
++test_usleep(useconds_t usec)
++{
++ struct timespec ts = {
++ .tv_sec = 0,
++ .tv_nsec = USEC_TO_NSEC(usec)
++ };
++
++ assert(nanosleep(&ts, NULL) == 0);
++}
++
++/* we must write the whole function instead of
++ * wrapping test_usleep, because useconds_t may not
++ * be able to contain such a big number of microseconds */
++void
++test_sleep(unsigned int sec)
++{
++ struct timespec ts = {
++ .tv_sec = sec,
++ .tv_nsec = 0
++ };
++
++ assert(nanosleep(&ts, NULL) == 0);
++}
++
++/** Try to disable coredumps
++ *
++ * Useful for tests that crash on purpose, to avoid creating a core file
++ * or launching an application crash handler service or cluttering coredumpctl.
++ *
++ * NOTE: Calling this may make the process undebuggable.
++ */
++void
++test_disable_coredumps(void)
++{
++ struct rlimit r;
++
++ if (getrlimit(RLIMIT_CORE, &r) == 0) {
++ r.rlim_cur = 0;
++ setrlimit(RLIMIT_CORE, &r);
++ }
++
++#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
++ prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
++#endif
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++#include "../config.h"
++
++#define _GNU_SOURCE
++
++#include <unistd.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <sys/stat.h>
++#include <string.h>
++#include <assert.h>
++#include <dlfcn.h>
++#include <errno.h>
++#include <limits.h>
++#include <signal.h>
++#include <sys/ptrace.h>
++#ifdef HAVE_SYS_PROCCTL_H
++#include <sys/procctl.h>
++#elif defined(HAVE_SYS_PRCTL_H)
++#include <sys/prctl.h>
++#ifndef PR_SET_PTRACER
++# define PR_SET_PTRACER 0x59616d61
++#endif
++#endif
++
++#include "test-runner.h"
++
++/* when set to 1, check if tests are not leaking opened files.
++ * It is turned on by default. It can be turned off by
++ * WAYLAND_TEST_NO_LEAK_CHECK environment variable. */
++int fd_leak_check_enabled;
++
++/* when this var is set to 0, every call to test_set_timeout() is
++ * suppressed - handy when debugging the test. Can be set by
++ * WAYLAND_TEST_NO_TIMEOUTS environment variable. */
++static int timeouts_enabled = 1;
++
++/* set to one if the output goes to the terminal */
++static int is_atty = 0;
++
++extern const struct test __start_test_section, __stop_test_section;
++
++static const struct test *
++find_test(const char *name)
++{
++ const struct test *t;
++
++ for (t = &__start_test_section; t < &__stop_test_section; t++)
++ if (strcmp(t->name, name) == 0)
++ return t;
++
++ return NULL;
++}
++
++static void
++usage(const char *name, int status)
++{
++ const struct test *t;
++
++ fprintf(stderr, "Usage: %s [TEST]\n\n"
++ "With no arguments, run all test. Specify test case to run\n"
++ "only that test without forking. Available tests:\n\n",
++ name);
++
++ for (t = &__start_test_section; t < &__stop_test_section; t++)
++ fprintf(stderr, " %s\n", t->name);
++
++ fprintf(stderr, "\n");
++
++ exit(status);
++}
++
++void
++test_set_timeout(unsigned int to)
++{
++ int re;
++
++ if (!timeouts_enabled) {
++ fprintf(stderr, "Timeouts suppressed.\n");
++ return;
++ }
++
++ re = alarm(to);
++ fprintf(stderr, "Timeout was %sset", re ? "re-" : "");
++
++ if (to != 0)
++ fprintf(stderr, " to %d second%s from now.\n",
++ to, to > 1 ? "s" : "");
++ else
++ fprintf(stderr, " off.\n");
++}
++
++static void
++sigalrm_handler(int signum)
++{
++ fprintf(stderr, "Test timed out.\n");
++ abort();
++}
++
++void
++check_fd_leaks(int supposed_fds)
++{
++ int num_fds;
++
++ if (fd_leak_check_enabled) {
++ num_fds = count_open_fds();
++ if (supposed_fds != num_fds) {
++ fprintf(stderr, "fd leak detected in test. "
++ "Opened %d files, unclosed %d\n", num_fds,
++ num_fds - supposed_fds);
++ abort();
++ }
++ } else {
++ fprintf(stderr, "FD leak checks disabled\n");
++ }
++}
++
++static void
++run_test(const struct test *t)
++{
++ int cur_fds;
++ struct sigaction sa;
++
++ if (timeouts_enabled) {
++ sa.sa_handler = sigalrm_handler;
++ sa.sa_flags = 0;
++ sigemptyset(&sa.sa_mask);
++ assert(sigaction(SIGALRM, &sa, NULL) == 0);
++ }
++
++ //cur_alloc = get_current_alloc_num();
++ cur_fds = count_open_fds();
++
++ t->run();
++
++ /* turn off timeout (if any) after test completion */
++ if (timeouts_enabled)
++ alarm(0);
++
++ check_fd_leaks(cur_fds);
++
++ exit(EXIT_SUCCESS);
++}
++
++#ifndef PATH_MAX
++#define PATH_MAX 256
++#endif
++
++static void
++set_xdg_runtime_dir(void)
++{
++ char xdg_runtime_dir[PATH_MAX];
++ const char *xrd_env;
++
++ xrd_env = getenv("XDG_RUNTIME_DIR");
++ /* if XDG_RUNTIME_DIR is not set in environ, fallback to /tmp */
++ assert((snprintf(xdg_runtime_dir, PATH_MAX, "%s/wayland-tests-XXXXXX",
++ (xrd_env && xrd_env[0] == '/') ? xrd_env : "/tmp") < PATH_MAX)
++ && "test error: XDG_RUNTIME_DIR too long");
++
++ assert(mkdtemp(xdg_runtime_dir) && "test error: mkdtemp failed");
++ if (mkdir(xdg_runtime_dir, 0700) == -1)
++ if (errno != EEXIST) {
++ perror("Creating XDG_RUNTIME_DIR");
++ abort();
++ }
++
++ if (setenv("XDG_RUNTIME_DIR", xdg_runtime_dir, 1) == -1) {
++ perror("Setting XDG_RUNTIME_DIR");
++ abort();
++ }
++}
++
++static void
++rmdir_xdg_runtime_dir(void)
++{
++ const char *xrd_env = getenv("XDG_RUNTIME_DIR");
++ assert(xrd_env && xrd_env[0] == '/' && "No XDG_RUNTIME_DIR set");
++
++ /* rmdir may fail if some test didn't do clean up */
++ if (rmdir(xrd_env) == -1)
++ perror("Cleaning XDG_RUNTIME_DIR");
++}
++
++#define RED "\033[31m"
++#define GREEN "\033[32m"
++
++static void
++stderr_set_color(const char *color)
++{
++ /* use colors only when the output is connected to
++ * the terminal */
++ if (is_atty)
++ fprintf(stderr, "%s", color);
++}
++
++static void
++stderr_reset_color(void)
++{
++ if (is_atty)
++ fprintf(stderr, "\033[0m");
++}
++
++/* this function is taken from libinput/test/litest.c
++ * (rev 028513a0a723e97941c39)
++ *
++ * Returns: 1 if a debugger is confirmed present; 0 if no debugger is
++ * present or if it can't be determined.
++ */
++#if defined(HAVE_SYS_PROCCTL_H) && defined(PROC_TRACE_STATUS)
++static int
++is_debugger_attached(void)
++{
++ int rc;
++ int status;
++ rc = procctl(P_PID, getpid(), PROC_TRACE_STATUS, &status);
++ if (rc == -1) {
++ perror("procctl");
++ return 0;
++ }
++ /* -1=tracing disabled, 0=no debugger attached, >0=pid of debugger. */
++ return status > 0;
++}
++#elif defined(HAVE_SYS_PRCTL_H)
++static int
++is_debugger_attached(void)
++{
++ int status;
++ int rc;
++ pid_t pid;
++ int pipefd[2];
++
++ if (pipe(pipefd) == -1) {
++ perror("pipe");
++ return 0;
++ }
++
++ pid = fork();
++ if (pid == -1) {
++ perror("fork");
++ close(pipefd[0]);
++ close(pipefd[1]);
++ return 0;
++ } else if (pid == 0) {
++ char buf;
++ pid_t ppid = getppid();
++
++ /* Wait until parent is ready */
++ close(pipefd[1]); /* Close unused write end */
++ read(pipefd[0], &buf, 1);
++ close(pipefd[0]);
++ if (buf == '-')
++ _exit(1);
++ if (ptrace(PTRACE_ATTACH, ppid, NULL, NULL) != 0)
++ _exit(1);
++ if (!waitpid(-1, NULL, 0))
++ _exit(1);
++ ptrace(PTRACE_CONT, NULL, NULL);
++ ptrace(PTRACE_DETACH, ppid, NULL, NULL);
++ _exit(0);
++ } else {
++ close(pipefd[0]);
++
++ /* Enable child to ptrace the parent process */
++ rc = prctl(PR_SET_PTRACER, pid);
++ if (rc != 0 && errno != EINVAL) {
++ /* An error prevents us from telling if a debugger is attached.
++ * Instead of propagating the error, assume no debugger present.
++ * But note the error to the log as a clue for troubleshooting.
++ * Then flag the error state to the client by sending '-'.
++ */
++ perror("prctl");
++ write(pipefd[1], "-", 1);
++ } else {
++ /* Signal to client that parent is ready by passing '+' */
++ write(pipefd[1], "+", 1);
++ }
++ close(pipefd[1]);
++
++ waitpid(pid, &status, 0);
++ rc = WEXITSTATUS(status);
++ }
++
++ return rc;
++}
++#endif
++
++int main(int argc, char *argv[])
++{
++ const struct test *t;
++ pid_t pid;
++ int total, pass;
++ siginfo_t info;
++
++ if (isatty(fileno(stderr)))
++ is_atty = 1;
++
++ if (is_debugger_attached()) {
++ fd_leak_check_enabled = 0;
++ timeouts_enabled = 0;
++ } else {
++ fd_leak_check_enabled = !getenv("WAYLAND_TEST_NO_LEAK_CHECK");
++ timeouts_enabled = !getenv("WAYLAND_TEST_NO_TIMEOUTS");
++ }
++
++ if (argc == 2 && strcmp(argv[1], "--help") == 0)
++ usage(argv[0], EXIT_SUCCESS);
++
++ if (argc == 2) {
++ t = find_test(argv[1]);
++ if (t == NULL) {
++ fprintf(stderr, "unknown test: \"%s\"\n", argv[1]);
++ usage(argv[0], EXIT_FAILURE);
++ }
++
++ set_xdg_runtime_dir();
++ /* run_test calls exit() */
++ assert(atexit(rmdir_xdg_runtime_dir) == 0);
++
++ run_test(t);
++ }
++
++ /* set our own XDG_RUNTIME_DIR */
++ set_xdg_runtime_dir();
++
++ pass = 0;
++ for (t = &__start_test_section; t < &__stop_test_section; t++) {
++ int success = 0;
++
++ pid = fork();
++ assert(pid >= 0);
++
++ if (pid == 0)
++ run_test(t); /* never returns */
++
++ if (waitid(P_PID, pid, &info, WEXITED)) {
++ stderr_set_color(RED);
++ fprintf(stderr, "waitid failed: %s\n",
++ strerror(errno));
++ stderr_reset_color();
++
++ abort();
++ }
++
++ switch (info.si_code) {
++ case CLD_EXITED:
++ if (info.si_status == EXIT_SUCCESS)
++ success = !t->must_fail;
++ else
++ success = t->must_fail;
++
++ stderr_set_color(success ? GREEN : RED);
++ fprintf(stderr, "test \"%s\":\texit status %d",
++ t->name, info.si_status);
++
++ break;
++ case CLD_KILLED:
++ case CLD_DUMPED:
++ if (t->must_fail)
++ success = 1;
++
++ stderr_set_color(success ? GREEN : RED);
++ fprintf(stderr, "test \"%s\":\tsignal %d",
++ t->name, info.si_status);
++
++ break;
++ }
++
++ if (success) {
++ pass++;
++ fprintf(stderr, ", pass.\n");
++ } else
++ fprintf(stderr, ", fail.\n");
++
++ stderr_reset_color();
++
++ /* print separator line */
++ fprintf(stderr, "----------------------------------------\n");
++ }
++
++ total = &__stop_test_section - &__start_test_section;
++ fprintf(stderr, "%d tests, %d pass, %d fail\n",
++ total, pass, total - pass);
++
++ /* cleaning */
++ rmdir_xdg_runtime_dir();
++
++ return pass == total ? EXIT_SUCCESS : EXIT_FAILURE;
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++#ifndef _TEST_RUNNER_H_
++#define _TEST_RUNNER_H_
++
++#ifdef NDEBUG
++#error "Tests must not be built with NDEBUG defined, they rely on assert()."
++#endif
++
++#include <unistd.h>
++
++struct test {
++ const char *name;
++ void (*run)(void);
++ int must_fail;
++} __attribute__ ((aligned (16)));
++
++#define TEST(name) \
++ static void name(void); \
++ \
++ const struct test test##name \
++ __attribute__ ((used, section ("test_section"))) = { \
++ #name, name, 0 \
++ }; \
++ \
++ static void name(void)
++
++#define FAIL_TEST(name) \
++ static void name(void); \
++ \
++ const struct test test##name \
++ __attribute__ ((used, section ("test_section"))) = { \
++ #name, name, 1 \
++ }; \
++ \
++ static void name(void)
++
++int
++count_open_fds(void);
++
++void
++exec_fd_leak_check(int nr_expected_fds); /* never returns */
++
++void
++check_fd_leaks(int supposed_fds);
++
++/*
++ * set/reset the timeout in seconds. The timeout starts
++ * at the point of invoking this function
++ */
++void
++test_set_timeout(unsigned int);
++
++/* test-runner uses alarm() and SIGALRM, so we can not
++ * use usleep and sleep functions in tests (see 'man usleep'
++ * or 'man sleep', respectively). Following functions are safe
++ * to use in tests */
++void
++test_usleep(useconds_t);
++
++void
++test_sleep(unsigned int);
++
++void
++test_disable_coredumps(void);
++
++#define DISABLE_LEAK_CHECKS \
++ do { \
++ extern int fd_leak_check_enabled; \
++ fd_leak_check_enabled = 0; \
++ } while (0);
++
++#endif
--- /dev/null
--- /dev/null
++AC_DEFUN([WAYLAND_SCANNER_RULES], [
++ PKG_PROG_PKG_CONFIG
++
++ PKG_CHECK_MODULES([WAYLAND_SCANNER], [wayland-scanner >= 1.14.0])
++
++ wayland_scanner=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner`
++ AC_SUBST([wayland_scanner])
++
++ wayland_scanner_rules=`$PKG_CONFIG --variable=pkgdatadir wayland-scanner`/wayland-scanner.mk
++ AC_SUBST_FILE([wayland_scanner_rules])
++
++ AC_SUBST([wayland_protocoldir], [$1])
++])
--- /dev/null
--- /dev/null
++%-protocol.c : $(wayland_protocoldir)/%.xml
++ $(AM_V_GEN)$(wayland_scanner) code $< $@
++
++%-server-protocol.h : $(wayland_protocoldir)/%.xml
++ $(AM_V_GEN)$(wayland_scanner) server-header $< $@
++
++%-client-protocol.h : $(wayland_protocoldir)/%.xml
++ $(AM_V_GEN)$(wayland_scanner) client-header $< $@